| Item | Method | Frequency | Location |
|---|---|---|---|
| Production VM | Proxmox snapshot | Before each deployment | Proxmox |
| Database | pg_dump | Before major changes | /home/crip/backups/ |
| Media files (PDFs) | Manual copy | Before deployments | Off-server |
| Code | GitHub | Every session commit | github.com/ounyai |
| .env file | Manual | After changes | Bitwarden (as note) |
| Wiki.js data | Docker volume | — | wikijs-db-data volume |
Before any major deployment:
https://nu.bylaw.com.au:8006pre-session-12-YYYYMMDDTo roll back to a snapshot:
# Create backup directory
mkdir -p /home/crip/backups
# Full database backup (uncompressed)
pg_dump -U yealinbilling -h localhost yealinbilling > /home/crip/backups/yealin_$(date +%Y%m%d_%H%M%S).sql
# Compressed backup (recommended)
pg_dump -U yealinbilling -h localhost yealinbilling | gzip > /home/crip/backups/yealin_$(date +%Y%m%d_%H%M%S).sql.gz
# Verify backup
ls -lh /home/crip/backups/
# From uncompressed backup
psql -U yealinbilling -h localhost yealinbilling < /home/crip/backups/yealin_20260608.sql
# From compressed backup
gunzip -c /home/crip/backups/yealin_20260608.sql.gz | psql -U yealinbilling -h localhost yealinbilling
PDF invoices are stored in /var/www/yealinbilling/media/invoices/. Copy these off-server:
# Copy to local machine via scp
scp -r crip@51.161.136.89:/var/www/yealinbilling/media/invoices/ ./invoices_backup/
Wiki.js data lives in a Docker volume. Backup:
# Backup Wiki.js database
docker exec wikijs-db pg_dump -U wikijs wikijs | gzip > /home/crip/backups/wikijs_$(date +%Y%m%d).sql.gz
The .env file contains all secrets. Never commit it to Git. Store it safely:
# View current .env (to copy into Bitwarden)
cat /var/www/yealinbilling/.env
Save as a secure note in Bitwarden called "Yealin Billing — Production .env"
If the production server is completely lost:
# Create user
adduser crip
usermod -aG sudo crip
# Switch to crip user
su - crip
sudo apt update
sudo apt install -y postgresql postgresql-client nginx redis-server \
python3-pip python3-venv python3-dev libpq-dev build-essential \
libssl-dev libffi-dev libcairo2 libpango-1.0-0 libpangocairo-1.0-0 \
libgdk-pixbuf-xlib-2.0-0 shared-mime-info curl git certbot \
python3-certbot-nginx pkg-config
# Install Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Install Docker
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker crip
sudo -u postgres psql
CREATE USER yealinbilling WITH PASSWORD 'YOUR_PASSWORD';
CREATE DATABASE yealinbilling OWNER yealinbilling;
GRANT ALL PRIVILEGES ON DATABASE yealinbilling TO yealinbilling;
\q
sudo mkdir -p /var/www/yealinbilling
sudo chown crip:crip /var/www/yealinbilling
cd /var/www
git clone https://YOUR_PAT@github.com/ounyai/yealin-billing.git yealinbilling
cd /var/www/yealinbilling
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
nano /var/www/yealinbilling/.env
# Paste complete .env contents from Bitwarden
chmod 600 /var/www/yealinbilling/.env
export DJANGO_SETTINGS_MODULE=config.settings.production
python manage.py migrate
python manage.py createsuperuser
python manage.py collectstatic --noinput
# If you have a backup, restore it
psql -U yealinbilling -h localhost yealinbilling < /path/to/backup.sql
python manage.py shell
# Seed settings, FX, Celery tasks — see Database Management page
cd /var/www/yealinbilling/frontend
npm install
npm run build
# Create gunicorn.service, celery.service, celerybeat.service
# (see Services & Systemd page for file contents)
sudo systemctl daemon-reload
sudo systemctl enable gunicorn celery celerybeat
sudo systemctl start gunicorn celery celerybeat
# Create /etc/nginx/sites-available/yealinbilling
# (see Nginx & SSL page for config)
sudo ln -s /etc/nginx/sites-available/yealinbilling /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx
sudo certbot --nginx -d billing.yealin.com.au --non-interactive --agree-tos -m co@aus.co
sudo usermod -aG crip www-data
sudo systemctl restart gunicorn nginx
sudo mkdir -p /opt/wikijs
sudo chown crip:crip /opt/wikijs
# Create docker-compose.yml (see Wiki Management page)
cd /opt/wikijs
docker compose up -d
# Configure Nginx for wiki.yealin.com.au
sudo certbot --nginx -d wiki.yealin.com.au --non-interactive --agree-tos -m co@aus.co
sudo systemctl status gunicorn celery celerybeat nginx postgresql redis-server --no-pager
curl -s https://billing.yealin.com.au/api/ # Should return 401