Private
Public Access
Fix deployment guide issues found during a live walkthrough
Three real, reproducible bugs in DEPLOYMENT.md's app-server setup steps, each found by actually following the guide on a real box rather than static review: - useradd --system --create-home is unreliable on Debian in both directions: sometimes it silently skips creating the home directory, sometimes it creates it AND populates it from /etc/skel (.bashrc/.profile/.bash_logout). Either way it broke a later step -- the skel files make git clone refuse to clone into a non-empty directory. Fixed by dropping --create-home and creating the directory ourselves, deferring anything else that goes in it (uploads/) until after the clone. - Documented a personal/deployment-user access token as a first-class alternative to the SSH deploy key for cloning, alongside its plaintext- in-.git/config tradeoff. - The create-user command nested a user-chosen password inside two layers of shell quoting (an outer bash -c '...' plus inner double quotes) -- fragile for any password with a space or a literal '. Replaced with dropping into an authenticated interactive shell first, so there's only one layer of quoting to get right at an actual prompt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+60
-9
@@ -105,12 +105,26 @@ sudo apt install -y python3 python3-venv nodejs npm git
|
|||||||
### 3a. The `ds-chat` system user and directory
|
### 3a. The `ds-chat` system user and directory
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo useradd --system --shell /usr/sbin/nologin --home-dir /srv/ds-chat --create-home ds-chat
|
sudo useradd --system --shell /usr/sbin/nologin --home-dir /srv/ds-chat ds-chat
|
||||||
|
# Deliberately no --create-home: on Debian, --system + --create-home is
|
||||||
|
# unreliable in *both* directions -- sometimes it silently skips creating
|
||||||
|
# the directory at all, sometimes it creates it and populates it from
|
||||||
|
# /etc/skel (.bashrc, .profile, .bash_logout), which then makes the git
|
||||||
|
# clone in the next step fail since it refuses to clone into a non-empty
|
||||||
|
# directory. Creating the directory ourselves, with no skel copying,
|
||||||
|
# sidesteps both failure modes.
|
||||||
|
sudo mkdir -p /srv/ds-chat
|
||||||
sudo chown ds-chat:ds-chat /srv/ds-chat
|
sudo chown ds-chat:ds-chat /srv/ds-chat
|
||||||
sudo -u ds-chat mkdir -p /srv/ds-chat/uploads
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3b. Clone the repo (deploy key, not a personal token)
|
Deliberately not creating `/srv/ds-chat/uploads` here -- `git clone` in the
|
||||||
|
next step refuses to clone into a non-empty directory, so anything created
|
||||||
|
inside `/srv/ds-chat` has to wait until after the clone. (The app would
|
||||||
|
also create this directory itself on first upload if it were missing --
|
||||||
|
see `app/storage.py` -- so this step is for clarity/permissions, not a
|
||||||
|
strict requirement.)
|
||||||
|
|
||||||
|
### 3b. Clone the repo (deploy key or access token)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo -u ds-chat mkdir -p /srv/ds-chat/.ssh
|
sudo -u ds-chat mkdir -p /srv/ds-chat/.ssh
|
||||||
@@ -129,6 +143,27 @@ sudo -u ds-chat git clone git@git.darksingularity.org:DarkSingularity/ds-chat.gi
|
|||||||
(If your Gitea's SSH is on a non-default port, adjust the clone URL and
|
(If your Gitea's SSH is on a non-default port, adjust the clone URL and
|
||||||
`ssh-keyscan -p <port>` accordingly.)
|
`ssh-keyscan -p <port>` accordingly.)
|
||||||
|
|
||||||
|
**Alternative: a personal/deployment-user access token instead of a deploy
|
||||||
|
key** — skip the `.ssh`/`ssh-keygen`/`ssh-keyscan` commands above entirely
|
||||||
|
and clone over HTTPS with the token embedded in the URL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u ds-chat git clone https://<TOKEN>@git.darksingularity.org/DarkSingularity/ds-chat.git /srv/ds-chat
|
||||||
|
```
|
||||||
|
|
||||||
|
The token then lives in plaintext in `/srv/ds-chat/.git/config` (`git
|
||||||
|
remote -v` shows it) — readable by root and the `ds-chat` user, not by
|
||||||
|
anyone else under normal file permissions. `deploy/upgrade.sh`'s later
|
||||||
|
`git pull`s reuse this same authenticated URL automatically, no extra
|
||||||
|
setup needed. Fine as long as the token is scoped to read-only access on
|
||||||
|
just this repo.
|
||||||
|
|
||||||
|
Either way, now that the repo is cloned:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u ds-chat mkdir -p /srv/ds-chat/uploads
|
||||||
|
```
|
||||||
|
|
||||||
### 3c. Backend: venv, env file, migrations, first admin
|
### 3c. Backend: venv, env file, migrations, first admin
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -150,15 +185,31 @@ Generate `SESSION_SECRET`:
|
|||||||
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
|
||||||
```
|
```
|
||||||
|
|
||||||
Run migrations and create the first admin account (as `ds-chat`, with the
|
Run migrations (as `ds-chat`, with the env file sourced so `DATABASE_URL`
|
||||||
env file sourced so `DATABASE_URL` is set):
|
is set) — safe as a single non-interactive command since nothing here is a
|
||||||
|
user-chosen value that could contain quotes/spaces/special characters:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo -u ds-chat bash -c 'set -a; source /etc/ds-chat/env; set +a; \
|
sudo -u ds-chat bash -c 'set -a; source /etc/ds-chat/env; set +a; cd /srv/ds-chat/backend && .venv/bin/alembic upgrade head'
|
||||||
cd /srv/ds-chat/backend && .venv/bin/alembic upgrade head'
|
```
|
||||||
|
|
||||||
sudo -u ds-chat bash -c 'set -a; source /etc/ds-chat/env; set +a; \
|
Creating the first admin account is different — the password is arbitrary
|
||||||
cd /srv/ds-chat/backend && .venv/bin/python -m app.cli create-user <ADMIN_USERNAME> <ADMIN_EMAIL> "<ADMIN_PASSWORD>" --admin'
|
user input, and wrapping it in a second layer of quoting inside the `bash
|
||||||
|
-c '...'` above is fragile (a space drops the rest of the password as
|
||||||
|
"unrecognized arguments"; a literal `'` in the password breaks the outer
|
||||||
|
quoting entirely). Drop into an authenticated shell first instead, so
|
||||||
|
there's only one layer of quoting to get right, at an actual prompt:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u ds-chat bash -c 'set -a; source /etc/ds-chat/env; set +a; exec bash'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, from inside that shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /srv/ds-chat/backend
|
||||||
|
.venv/bin/python -m app.cli create-user <ADMIN_USERNAME> <ADMIN_EMAIL> "<ADMIN_PASSWORD>" --admin
|
||||||
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional: push notifications. Skipped silently if `VAPID_PUBLIC_KEY`/
|
Optional: push notifications. Skipped silently if `VAPID_PUBLIC_KEY`/
|
||||||
|
|||||||
Reference in New Issue
Block a user