-
Verify cloud-init — run cloud-init status. If not done, retry every 10 seconds for up to 120 seconds. If still not done at the end of the wait, report the current status and stop — do not proceed.
-
Locate and mount data volume:
a. Run lsblk to identify the data volume device. On Cyso/OpenStack, Cinder volumes appear as /dev/sdb (virtio-scsi), not /dev/vdb (virtio-blk).
b. Check for an existing filesystem: sudo blkid <device>. If no filesystem is reported, format: sudo mkfs.ext4 <device>. If a filesystem already exists, skip formatting.
c. Create the mount point and mount:
sudo mkdir -p /data
sudo mount <device> /data
d. Register in fstab using UUID (not device path):
echo "UUID=$(sudo blkid -s UUID -o value <device>) /data ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
e. Verify: mount | grep /data
-
Fix app directory ownership — cloud-init creates /opt/him/ as root; always correct this:
sudo chown -R ubuntu:ubuntu /opt/him
If /opt/him/ does not exist, create it first: sudo mkdir -p /opt/him && sudo chown ubuntu:ubuntu /opt/him
-
Create .env file:
a. Write the following to /opt/him/.env (these are the minimum required values):
NODE_ENV=production
PORT=3001
DB_PATH=/data/him.db
b. Set permissions: chmod 600 /opt/him/.env
c. Do NOT write ANTHROPIC_API_KEY to this file now. Populate it manually via SSH after deployment is complete — never write its value to any file tracked in version control or stored in Terraform state.
-
Add ubuntu to docker group:
sudo usermod -aG docker ubuntu
newgrp docker
usermod does not take effect in the current SSH session. newgrp docker activates the group for the current session. CI/CD pipelines use a fresh SSH session and inherit the updated group automatically.
-
Smoke test — run docker ps. Expected result: empty container list with no permission error.