Compare commits

...

6 Commits

Author SHA1 Message Date
valknar e3cd2df372 docs: document stacks.sh in README
Replace manual docker compose / systemctl snippets with stacks.sh
equivalents and add a dedicated section covering all commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:55:05 +02:00
valknar 067d017ea6 feat(stacks): add --static flag to completion command
Bakes the current stack list into the generated completion script instead
of using runtime directory discovery. Useful for remote hosts where the
stacks dir path differs from the local repo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:52:55 +02:00
valknar 3251f27edb feat: add stacks.sh stack manager CLI
Bash script for managing Docker Compose stacks with glob filtering,
parallel execution, service management, scaffolding, and shell completion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:13:43 +02:00
valknar cf32e669cb fix(gitea): use .RunModeIsProd and hardcode Umami values in header template
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:34:21 +02:00
valknar e613d766ec fix(gitea): revert to UMAMI_ID/UMAMI_SRC and use .UmamiSrc/.UmamiId template vars
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:26:39 +02:00
valknar 53608a7195 fix(gitea): use .UmamiSrc/.UmamiScript template vars for Umami analytics
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:24:57 +02:00
5 changed files with 1238 additions and 29 deletions
+73 -23
View File
@@ -20,11 +20,72 @@ Each stack is independently deployable with its own `compose.yml` and `.env`. Al
## Tools ## Tools
| Directory | Description | | File/Directory | Description |
|---|---| |---|---|
| `stacks.sh` | CLI to manage stacks, services, and scaffolding |
| `_backup` | Daily restic backups to HiDrive (host script + systemd timer) | | `_backup` | Daily restic backups to HiDrive (host script + systemd timer) |
| `_update` | Nightly image update check + prune (host script + systemd timer) | | `_update` | Nightly image update check + prune (host script + systemd timer) |
## stacks.sh
`stacks.sh` is the primary management CLI. It wraps `docker compose` with glob-based multi-stack targeting, manages the update and backup systemd services, scaffolds new stacks, and generates shell completions.
```bash
./stacks.sh help
```
**Stack commands** — all accept one or more stack names or glob patterns (omit for all stacks):
```bash
./stacks.sh ls # list all stacks with live container status
./stacks.sh ps gitea # container status table
./stacks.sh up # start all stacks
./stacks.sh up gitea traefik # start specific stacks
./stacks.sh down 'g*' # stop stacks matching glob
./stacks.sh restart 'g*,traefik' # glob + exact name, comma-separated
./stacks.sh pull --parallel # pull all images in parallel
./stacks.sh logs -f gitea # follow logs
./stacks.sh logs -n 100 gitea n8n # tail multiple stacks
./stacks.sh exec gitea gitea gitea admin user list # exec in container
./stacks.sh run passbolt passbolt bin/cake passbolt healthcheck
```
**Service management:**
```bash
./stacks.sh update install # link & enable systemd update timer
./stacks.sh update run # run update now
./stacks.sh update status # show timer/service status
./stacks.sh update logs # show journal logs
./stacks.sh backup install # link & enable systemd backup timer
./stacks.sh backup run # run backup now
./stacks.sh backup snapshots # list restic snapshots
```
**Scaffold a new stack:**
```bash
./stacks.sh new myapp # basic stack with Traefik labels
./stacks.sh new myapp --db postgres # with Postgres service
./stacks.sh new myapp --db postgres --redis # with Postgres + Redis
./stacks.sh new myapp --no-traefik # expose port instead of Traefik
```
Generates `compose.yml` (with healthchecks, `../.data/` volumes, Traefik labels) and `.env.example`.
**Shell completion:**
```bash
# Dynamic — discovers stacks at tab-complete time (default)
./stacks.sh completion zsh --install
# Static — bakes current stack list in; useful on the VPS
./stacks.sh completion zsh --static --install
```
**Global flags:** `--dry-run`, `--parallel`, `--verbose`, `--quiet`
## Deployment ## Deployment
```bash ```bash
@@ -53,19 +114,13 @@ rsync -avz _backup/ vps:~/stacks/_backup/
# Initialize restic repo (first time only) # Initialize restic repo (first time only)
ssh vps 'source ~/stacks/_backup/.env && restic init -r /mnt/hidrive/users/valknar/Backup/stacks' ssh vps 'source ~/stacks/_backup/.env && restic init -r /mnt/hidrive/users/valknar/Backup/stacks'
# Install systemd units # Install systemd units (or use stacks.sh on the VPS)
ssh vps 'ln -sf ~/stacks/_backup/stacks-backup.service /etc/systemd/system/ && \ ssh vps '~/stacks/stacks.sh backup install'
ln -sf ~/stacks/_backup/stacks-backup.timer /etc/systemd/system/ && \
systemctl daemon-reload && systemctl enable --now stacks-backup.timer'
# Manual test run # Manual run / status
ssh vps '~/stacks/_backup/backup.sh' ssh vps '~/stacks/stacks.sh backup run'
ssh vps '~/stacks/stacks.sh backup status'
# Check timer status ssh vps '~/stacks/stacks.sh backup snapshots'
ssh vps 'systemctl status stacks-backup.timer'
# View snapshots
ssh vps 'source ~/stacks/_backup/.env && restic -r /mnt/hidrive/users/valknar/Backup/stacks snapshots'
``` ```
## Updates ## Updates
@@ -75,18 +130,13 @@ The `_update` script runs nightly at 2:00 AM. It pulls the latest image for ever
```bash ```bash
# Deploy update stack # Deploy update stack
rsync -avz _update/ vps:~/stacks/_update/ rsync -avz _update/ vps:~/stacks/_update/
ssh vps 'chmod +x ~/stacks/_update/update.sh'
# Install systemd units # Install systemd units (or use stacks.sh on the VPS)
ssh vps 'ln -sf ~/stacks/_update/stacks-update.service /etc/systemd/system/ && \ ssh vps '~/stacks/stacks.sh update install'
ln -sf ~/stacks/_update/stacks-update.timer /etc/systemd/system/ && \
systemctl daemon-reload && systemctl enable --now stacks-update.timer'
# Manual test run # Manual run / status
ssh vps '~/stacks/_update/update.sh' ssh vps '~/stacks/stacks.sh update run'
ssh vps '~/stacks/stacks.sh update status'
# Check timer status
ssh vps 'systemctl status stacks-update.timer'
``` ```
## Notifications ## Notifications
-2
View File
@@ -3,5 +3,3 @@ NETWORK_NAME=falcon_network
RUNNER_TOKEN=change_me RUNNER_TOKEN=change_me
EMAIL_FROM=gitea@pivoine.art EMAIL_FROM=gitea@pivoine.art
EMAIL_USER=Gitea EMAIL_USER=Gitea
UMAMI_SRC=https://umami.example.com/script.js
UMAMI_ID=
-2
View File
@@ -36,8 +36,6 @@ services:
GITEA__ui__THEMES: gitea-auto,gitea-light,gitea-dark,arc-green,edge-auto,edge-dark,edge-light,everforest-auto,everforest-dark,everforest-light,gruvbox-auto,gruvbox-dark,gruvbox-light,gruvbox-material-auto,gruvbox-material-dark,gruvbox-material-light,nord,palenight,soft-era,sonokai,sonokai-andromeda,sonokai-atlantis,sonokai-espresso,sonokai-maia,sonokai-shusia GITEA__ui__THEMES: gitea-auto,gitea-light,gitea-dark,arc-green,edge-auto,edge-dark,edge-light,everforest-auto,everforest-dark,everforest-light,gruvbox-auto,gruvbox-dark,gruvbox-light,gruvbox-material-auto,gruvbox-material-dark,gruvbox-material-light,nord,palenight,soft-era,sonokai,sonokai-andromeda,sonokai-atlantis,sonokai-espresso,sonokai-maia,sonokai-shusia
GITEA__ui__DEFAULT_THEME: nord GITEA__ui__DEFAULT_THEME: nord
GITEA__ui__ENABLE_FEED: "true" GITEA__ui__ENABLE_FEED: "true"
UMAMI_SRC: ${UMAMI_SRC}
UMAMI_ID: ${UMAMI_ID}
ports: ports:
- "2222:2222" - "2222:2222"
volumes: volumes:
+2 -2
View File
@@ -1,3 +1,3 @@
{{if and (eq .RunMode "prod") (not .IsSigned)}} {{if and .RunModeIsProd (not .IsSigned)}}
<script defer src="{{env "UMAMI_SRC"}}" data-website-id="{{env "UMAMI_ID"}}"></script> <script defer src="https://umami.pivoine.art/script.js" data-website-id="eee7e810-116b-408a-a46d-f51dcec217c2"></script>
{{end}} {{end}}
Executable
+1163
View File
File diff suppressed because it is too large Load Diff