Private
Public Access
Rename project from KeepItTalking to DS Chat
Renames the app's display name everywhere (page titles, PWA manifest, TopBar, email subject lines, HMAC signature header) and its internal technical slug from chatapp to ds-chat/ds_chat: the Python package name and console script, the systemd unit and its user/group/paths, the deploy scripts, the Docker container names, and the Postgres database name. The live dev Postgres role stays "chatapp" -- renaming a role requires disconnecting the session using it, which needed a temporary superuser role Claude's auto-mode classifier correctly declined to create unsupervised. Functionally invisible (it's just a login credential), but worth knowing about if this ever needs fully cleaning up by hand. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+13
-13
@@ -1,27 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Nightly Postgres backup for the KeepItTalking data server.
|
||||
# Nightly Postgres backup for the DS Chat data server.
|
||||
#
|
||||
# Install (as root, on the data server):
|
||||
# sudo cp deploy/backup-postgres.sh /usr/local/bin/chatapp-backup-postgres.sh
|
||||
# sudo chmod 0700 /usr/local/bin/chatapp-backup-postgres.sh
|
||||
# sudo cp deploy/backup-postgres.sh /usr/local/bin/ds-chat-backup-postgres.sh
|
||||
# sudo chmod 0700 /usr/local/bin/ds-chat-backup-postgres.sh
|
||||
# sudo crontab -e
|
||||
# # add:
|
||||
# 0 3 * * * /usr/local/bin/chatapp-backup-postgres.sh
|
||||
# 0 3 * * * /usr/local/bin/ds-chat-backup-postgres.sh
|
||||
#
|
||||
# See ../DEPLOYMENT.md for the full data-server setup this fits into.
|
||||
#
|
||||
# Covers Postgres only. Uploaded chat images live on the app server's disk
|
||||
# (/srv/chatapp/uploads, see app/storage.py), not here -- see DEPLOYMENT.md
|
||||
# (/srv/ds-chat/uploads, see app/storage.py), not here -- see DEPLOYMENT.md
|
||||
# §7 for that gap.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DB_NAME="chatapp"
|
||||
DB_USER="chatapp"
|
||||
BACKUP_DIR="/var/backups/chatapp"
|
||||
DB_NAME="ds_chat"
|
||||
DB_USER="ds_chat"
|
||||
BACKUP_DIR="/var/backups/ds-chat"
|
||||
RETENTION_DAYS=14
|
||||
TIMESTAMP="$(date +%F-%H%M%S)"
|
||||
DEST="${BACKUP_DIR}/chatapp-${TIMESTAMP}.sql.gz"
|
||||
DEST="${BACKUP_DIR}/ds-chat-${TIMESTAMP}.sql.gz"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
@@ -35,7 +35,7 @@ echo "Backed up ${DB_NAME} to ${DEST}"
|
||||
|
||||
# Local rotation -- keep RETENTION_DAYS days on this box regardless of
|
||||
# whether off-box shipping (below) is configured yet.
|
||||
find "$BACKUP_DIR" -name 'chatapp-*.sql.gz' -mtime "+${RETENTION_DAYS}" -delete
|
||||
find "$BACKUP_DIR" -name 'ds-chat-*.sql.gz' -mtime "+${RETENTION_DAYS}" -delete
|
||||
|
||||
# --- Off-box shipping -------------------------------------------------
|
||||
# Not configured yet -- destination wasn't decided as of this script being
|
||||
@@ -44,9 +44,9 @@ find "$BACKUP_DIR" -name 'chatapp-*.sql.gz' -mtime "+${RETENTION_DAYS}" -delete
|
||||
#
|
||||
# rsync (to a second host reachable by the data server, e.g. over the same
|
||||
# private network / a WireGuard tunnel used for anything else):
|
||||
# rsync -a "$DEST" backup-user@backup-host:/path/to/chatapp-backups/
|
||||
# rsync -a "$DEST" backup-user@backup-host:/path/to/ds-chat-backups/
|
||||
#
|
||||
# S3-compatible object storage (needs `aws configure` or rclone set up
|
||||
# separately first):
|
||||
# aws s3 cp "$DEST" s3://your-bucket/chatapp-backups/
|
||||
# # or: rclone copy "$DEST" remote:chatapp-backups/
|
||||
# aws s3 cp "$DEST" s3://your-bucket/ds-chat-backups/
|
||||
# # or: rclone copy "$DEST" remote:ds-chat-backups/
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# /etc/chatapp/env (production)
|
||||
# /etc/ds-chat/env (production)
|
||||
#
|
||||
# This file is loaded by systemd's EnvironmentFile= (see
|
||||
# deploy/systemd/chatapp.service) directly into the app process's
|
||||
# deploy/systemd/ds-chat.service) directly into the app process's
|
||||
# environment -- it is NOT a dotenv file Python reads from a working
|
||||
# directory, and it must never be committed to the repository.
|
||||
#
|
||||
# Install:
|
||||
# sudo mkdir -p /etc/chatapp
|
||||
# sudo cp deploy/chatapp.env.example /etc/chatapp/env
|
||||
# sudo chown root:chatapp /etc/chatapp/env
|
||||
# sudo chmod 0640 /etc/chatapp/env
|
||||
# sudo mkdir -p /etc/ds-chat
|
||||
# sudo cp deploy/ds-chat.env.example /etc/ds-chat/env
|
||||
# sudo chown root:ds-chat /etc/ds-chat/env
|
||||
# sudo chmod 0640 /etc/ds-chat/env
|
||||
# # then edit in the real values below
|
||||
#
|
||||
# See ../DEPLOYMENT.md for how each value is generated.
|
||||
@@ -17,7 +17,7 @@
|
||||
# Points at the data server's PRIVATE address -- never the public one.
|
||||
# The role/password here are whatever you created on the data server in
|
||||
# DEPLOYMENT.md step 2.
|
||||
DATABASE_URL=postgresql+asyncpg://chatapp:REPLACE_ME@<DATA_SERVER_PRIVATE_IP>:5432/chatapp
|
||||
DATABASE_URL=postgresql+asyncpg://ds_chat:REPLACE_ME@<DATA_SERVER_PRIVATE_IP>:5432/ds_chat
|
||||
|
||||
# Generate with: python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
||||
SESSION_SECRET=REPLACE_ME
|
||||
@@ -1,8 +1,8 @@
|
||||
# /etc/systemd/system/chatapp.service
|
||||
# /etc/systemd/system/ds-chat.service
|
||||
#
|
||||
# Install: sudo cp deploy/systemd/chatapp.service /etc/systemd/system/
|
||||
# Install: sudo cp deploy/systemd/ds-chat.service /etc/systemd/system/
|
||||
# sudo systemctl daemon-reload
|
||||
# sudo systemctl enable --now chatapp
|
||||
# sudo systemctl enable --now ds-chat
|
||||
#
|
||||
# See ../../DEPLOYMENT.md for the full app-server setup this fits into.
|
||||
# TLS termination and public-facing reverse proxying are handled by an
|
||||
@@ -10,17 +10,17 @@
|
||||
# unit just needs to be reachable on the TCP port below.
|
||||
|
||||
[Unit]
|
||||
Description=KeepItTalking chat service app server
|
||||
Description=DS Chat app server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# No Type= override -- defaults to "simple", which is correct here since
|
||||
# gunicorn runs in the foreground (no --daemon flag below) and doesn't send
|
||||
# systemd's sd_notify readiness protocol.
|
||||
User=chatapp
|
||||
Group=chatapp
|
||||
WorkingDirectory=/srv/chatapp/backend
|
||||
EnvironmentFile=/etc/chatapp/env
|
||||
User=ds-chat
|
||||
Group=ds-chat
|
||||
WorkingDirectory=/srv/ds-chat/backend
|
||||
EnvironmentFile=/etc/ds-chat/env
|
||||
Environment=PYTHONUNBUFFERED=1
|
||||
|
||||
# 0.0.0.0 because Nginx Proxy Manager runs on a separate host -- the actual
|
||||
@@ -28,7 +28,7 @@ Environment=PYTHONUNBUFFERED=1
|
||||
# port to NPM's IP specifically, not the bind address. If NPM reaches this
|
||||
# box over a private network interface, bind to that private IP instead
|
||||
# for defense in depth (belt-and-suspenders on top of the firewall rule).
|
||||
ExecStart=/srv/chatapp/backend/.venv/bin/gunicorn app.main:app \
|
||||
ExecStart=/srv/ds-chat/backend/.venv/bin/gunicorn app.main:app \
|
||||
-k uvicorn.workers.UvicornWorker \
|
||||
--workers 4 \
|
||||
--bind 0.0.0.0:8000 \
|
||||
+12
-12
@@ -1,20 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Day-2 deploy/upgrade script for the KeepItTalking app server. Run by hand
|
||||
# over SSH as the `chatapp` user (or via sudo -u chatapp):
|
||||
# Day-2 deploy/upgrade script for the DS Chat app server. Run by hand
|
||||
# over SSH as the `ds-chat` user (or via sudo -u ds-chat):
|
||||
#
|
||||
# sudo -u chatapp /srv/chatapp/deploy/upgrade.sh
|
||||
# sudo -u ds-chat /srv/ds-chat/deploy/upgrade.sh
|
||||
#
|
||||
# Fails loudly and stops before touching the running service if any step
|
||||
# fails -- the previous deploy keeps running rather than being torn down
|
||||
# mid-upgrade. See ../DEPLOYMENT.md for what each step assumes is already
|
||||
# in place (venv, /etc/chatapp/env, the systemd unit, Node.js).
|
||||
# in place (venv, /etc/ds-chat/env, the systemd unit, Node.js).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="/srv/chatapp"
|
||||
REPO_DIR="/srv/ds-chat"
|
||||
BACKEND_DIR="${REPO_DIR}/backend"
|
||||
FRONTEND_DIR="${REPO_DIR}/frontend"
|
||||
ENV_FILE="/etc/chatapp/env"
|
||||
ENV_FILE="/etc/ds-chat/env"
|
||||
|
||||
echo "==> Pulling latest code"
|
||||
cd "$REPO_DIR"
|
||||
@@ -28,7 +28,7 @@ echo "==> Running database migrations"
|
||||
# alembic reads DATABASE_URL from the environment (backend/alembic/env.py),
|
||||
# so the env file has to actually be sourced into this shell first -- it's
|
||||
# not read automatically just because systemd's EnvironmentFile= points at
|
||||
# it (that only applies to the chatapp.service process, not this script).
|
||||
# it (that only applies to the ds-chat.service process, not this script).
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
source "$ENV_FILE"
|
||||
@@ -40,20 +40,20 @@ cd "$FRONTEND_DIR"
|
||||
npm ci --silent
|
||||
npm run build --silent
|
||||
|
||||
echo "==> Restarting chatapp"
|
||||
echo "==> Restarting ds-chat"
|
||||
# Active WebSocket connections drop here and reconnect automatically within
|
||||
# a few seconds (frontend/src/ws/useChatSocket.ts's exponential-backoff
|
||||
# reconnect) -- expected, not a bug, and not worth a blue-green setup for.
|
||||
sudo systemctl restart chatapp
|
||||
sudo systemctl restart ds-chat
|
||||
|
||||
echo "==> Verifying"
|
||||
sleep 2
|
||||
if curl -sf http://127.0.0.1:8000/api/health >/dev/null; then
|
||||
echo "Health check OK"
|
||||
else
|
||||
echo "Health check FAILED -- check: sudo journalctl -u chatapp -n 50" >&2
|
||||
echo "Health check FAILED -- check: sudo journalctl -u ds-chat -n 50" >&2
|
||||
exit 1
|
||||
fi
|
||||
sudo systemctl status chatapp --no-pager -l | head -10
|
||||
sudo systemctl status ds-chat --no-pager -l | head -10
|
||||
|
||||
echo "==> Done. journalctl -u chatapp -f to watch logs."
|
||||
echo "==> Done. journalctl -u ds-chat -f to watch logs."
|
||||
|
||||
Reference in New Issue
Block a user