Commit Graph
84 Commits
Author SHA1 Message Date
valknarandClaude Sonnet 4.6 8797a42d61 fix(gitea): bind SSH explicitly to IPv4 to avoid conflict with sshd on IPv6
Docker binds to both [::]:22 and 0.0.0.0:22 without an explicit IP,
conflicting with sshd on [::]:22.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 20:25:59 +02:00
valknarandClaude Sonnet 4.6 1e5d5254a6 feat(gitea): expose SSH on port 22
sshd is now IPv6-only (ListenAddress ::, bindv6only=1), freeing
IPv4 port 22 for Gitea SSH.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 20:25:42 +02:00
valknarandClaude Sonnet 4.6 0f943b5a62 fix(coolify): switch PHP-FPM from ondemand to dynamic mode
ondemand kills all workers after 10s idle, causing cold Laravel
bootstrap (10-54s) on every request after any quiet period.
dynamic keeps min_spare_servers=1 alive at all times; the other
PM_* values (start_servers=2, min=1, max_spare=3) were already
set but ignored under ondemand.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 11:06:07 +02:00
valknarandClaude Sonnet 4.6 8d33836714 fix(gitea): block scraper IP and add rate limiting
74.7.243.196 was crawling valknar/home SVG icon tree at 1.8 req/s.
- Denylist the IP in fail2ban dynamic config
- Add rate-limit@file middleware to Gitea's Traefik router to throttle
  future scrapers on public repos

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 10:27:56 +02:00
valknarandClaude Sonnet 4.6 3265d69a6c fix(traefik): upgrade fail2ban plugin to v0.9.0 and fix config schema
v0.7.1 caused 403 on all routes. v0.9.0 renamed whitelist→allowlist,
changed ip to a comma-separated string, and added enabled/statuscode fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 10:09:37 +02:00
valknarandClaude Sonnet 4.6 586f137cf9 feat(traefik): add fail2ban plugin with global middleware
Registers tomMoulard/fail2ban v0.7.1 as an experimental plugin and
applies it globally on the web-secure entrypoint alongside security-headers.
Bans IPs after 5 failures within 10 minutes for 3 hours; whitelists
RFC1918 ranges to protect internal/Docker traffic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 10:05:11 +02:00
valknarandClaude Sonnet 4.6 b69951f917 fix(help): align update subcommands and add backup descriptions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 23:49:57 +02:00
valknarandClaude Sonnet 4.6 d7829cb5ae docs: fix README backup/update/notifications sections
- Source .env before restic init so RESTIC_REPOSITORY is available
- Remove stale references to deleted _backup/.env and _update/.env
- Update Notifications section to point at root .env

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:13:00 +02:00
valknarandClaude Sonnet 4.6 8ae9c9e878 fix(update): compare local image store IDs, not running container IDs
docker compose images -q reports the image IDs of currently running
containers, which don't change after a pull — so before == after always
and containers were never recreated.

Fix: resolve each service's image tag to its local SHA256 ID via
docker image inspect, which reads the local image store and correctly
reflects the newly pulled image. Falls back from 'config --images'
(compose v2.19+) to parsing 'config' yaml for older versions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 21:09:56 +02:00
valknarandClaude Sonnet 4.6 fcff6f3298 refactor: absorb _backup and _update into stacks.sh
- Inline update logic (pull → compare digests → up -d → prune → notify)
- Inline backup logic with dynamic Postgres detection: any running
  <stack>_db container is dumped using the <stack>/<stack> convention
- Systemd unit files are now generated on `install` from embedded
  heredocs pointing at stacks.sh itself — no external scripts needed
- Root .env (WEBHOOK_URL, RESTIC_REPOSITORY, RESTIC_PASSWORD) replaces
  the per-service .env files in _backup/ and _update/
- Remove _backup/ and _update/ directories entirely
- Update README accordingly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:56:04 +02:00
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 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
valknarandClaude Sonnet 4.6 735adfabea feat(gitea): add conditional Umami analytics via env vars in header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 10:17:19 +02:00
valknarandClaude Sonnet 4.6 a9eb3de90d docs: add code stack to README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:18:17 +02:00
valknarandClaude Sonnet 4.6 c27a012d54 fix(code): consolidate volumes into single /home/coder mount
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:05:43 +02:00
valknarandClaude Sonnet 4.6 d367540eac fix(code): mount workspace volume to /home/coder/workspace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:01:19 +02:00
valknarandClaude Sonnet 4.6 c0aa3acbfc fix(code): mount workspace volume to /home/coder for full home persistence
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 17:59:53 +02:00
valknarandClaude Sonnet 4.6 d9bbfea9c4 fix(code): remove separate workspace volume
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 17:53:22 +02:00
valknarandClaude Sonnet 4.6 27c9e1c8a5 feat(code): add code-server stack with Traefik and Anthropic API support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 17:31:58 +02:00
valknarandClaude Sonnet 4.6 d4327bd152 fix(update): detect real image changes and improve webhook messages
Use image ID diff instead of grepping "Pulled" (which appears even
when images are already up to date). Add timestamp, stack count, and
updated/total ratio to all notification messages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 07:58:55 +02:00
valknarandClaude Sonnet 4.6 2130069836 fix(update): set executable bit on update.sh in git index
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 07:41:24 +02:00
valknarandClaude Sonnet 4.6 6eb603205a fix(update): make update.sh executable and fix Pulled grep pattern
- Add +x permission to update.sh (was causing systemd 203/EXEC failure)
- Remove $ anchor from grep so trailing space in docker output is matched
- Add .data/ to .gitignore

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 16:19:36 +00:00
valknarandClaude Sonnet 4.6 f231dd5432 feat: externalize EMAIL_FROM and EMAIL_USER to .env for gitea and passbolt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 18:38:22 +02:00
valknarandClaude Sonnet 4.6 afec1c03f5 feat(gitea): set mailer FROM address
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 18:01:08 +02:00
valknarandClaude Sonnet 4.6 9c7a34e9c0 feat: remove Affine stack
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 13:43:21 +02:00
valknarandClaude Sonnet 4.6 40dfe5776a feat(gitea): add Umami analytics via direct custom header template
Mount templates/custom/ directly to Gitea's default GITEA_CUSTOM templates
path. No entrypoint override or envsubst needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:58:25 +02:00
valknarandClaude Sonnet 4.6 e5e6a2c302 feat(gitea): add Umami analytics via custom header template
Injects the Umami tracking script into every Gitea page using a custom
header.tmpl generated at startup via envsubst. Script URL and website ID
are externalized to UMAMI_SCRIPT_URL / UMAMI_WEBSITE_ID env vars.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:49:26 +02:00
valknarandClaude Sonnet 4.6 9c65cfc9e3 revert(passbolt): remove clock-skew patch — metadata key already created
The patched PublicKeyValidationService.php and its volume mount are
no longer needed now that the metadata key exists in the database.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:48:41 +02:00
valknarandClaude Sonnet 4.6 15ce2e3f4b chore: remove accidentally committed log file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:47:34 +02:00
valknarandClaude Sonnet 4.6 300c685d50 feat: remove Vaultwarden — migrated to Passbolt
Credentials migrated to Passbolt CE at passbolt.pivoine.art.
Removed stack files and README entry. Data wiped on VPS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:47:07 +02:00
valknarandClaude Sonnet 4.6 5c398ee77c fix(passbolt): add 300s clock-skew tolerance to key creation date check
The isNotCreatedInTheFutureRule has zero tolerance, causing the
browser extension to fail when generating a metadata key if the
browser clock is even 1 second ahead of the server. Patching
isDateInFuture to allow 300 seconds tolerance and mounting the
file as a read-only volume so the fix survives image updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:16:56 +02:00
valknarandClaude Sonnet 4.6 2e31c1dcc9 fix(passbolt): persist GPG keyring as volume to survive restarts
Passbolt's entrypoint creates /var/lib/passbolt/.gnupg/pubring.kbx
as root while PHP-FPM runs as www-data. Without a volume this file
is recreated with wrong ownership on every container recreate, breaking
all GPG operations. Mounting the dir as a volume keeps the chown
33:33 fix permanent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 21:44:20 +02:00
valknarandClaude Sonnet 4.6 6f12bf9af7 fix(passbolt): disable metadata encryption for new instance setup
Passbolt 5.x's isNotCreatedInTheFutureRule has zero tolerance for
clock skew — even 1 second between browser and server causes the
metadata key creation to fail during first setup. Disabling the
automatic metadata setup for new instances allows the browser
extension to complete account setup successfully.

Encrypted metadata can be enabled from the admin panel post-setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 21:24:51 +02:00
valknarandClaude Sonnet 4.6 758e69300f fix(passbolt): add TZ env var (Europe/Amsterdam)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 21:06:01 +02:00
valknarandClaude Sonnet 4.6 ae81935376 fix(passbolt): clean setup with correct GPG fingerprint
Passbolt 5.x does not auto-persist the server key fingerprint across
container restarts (no passbolt.php is written). The fingerprint env var
is required and corresponds to the key auto-generated on first clean start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 20:39:55 +02:00
valknarandClaude Sonnet 4.6 d8cfcd23d1 fix(passbolt): fix DB hostname, encoding, and GPG fingerprint
- Use container_name passbolt_db instead of service name db (service names
  are ambiguous on the shared falcon_network — 6 other stacks also have a
  service named db)
- Add DATASOURCES_DEFAULT_ENCODING=utf8 to override MySQL's utf8mb4 default
- Add DATASOURCES_QUOTE_IDENTIFIER=true for PostgreSQL identifier quoting
- Set PASSBOLT_GPG_SERVER_KEY_FINGERPRINT for the auto-generated server key
- Add PASSBOLT_GPG_SERVER_KEY_EMAIL for correct server key identity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 20:14:57 +02:00
valknarandClaude Sonnet 4.6 a1f0f7091b feat(passbolt): add Passbolt CE stack
Password manager with GPG encryption. Uses PostgreSQL for consistency
with other stacks. Backed up alongside existing databases. Vaultwarden
kept running during migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 20:00:05 +02:00
valknarandClaude Sonnet 4.6 31841d1ac3 fix(compose): remove empty labels keys left after watchtower label removal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 19:44:01 +02:00
valknarandClaude Sonnet 4.6 4c522961a9 feat(_update): replace watchtower with custom nightly update script
Removes the watchtower container in favour of a host-side script that
runs daily at 2:00 AM via systemd timer.  Mirrors the _backup pattern:
auto-discovers stacks, pulls images, recreates changed containers,
prunes dangling images, and notifies via n8n → Telegram.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 19:42:25 +02:00
valknarandClaude Sonnet 4.6 cb241c9696 feat(affine): add SMTP config, AFFINE_SERVER_EXTERNAL_URL; remove blinko dir
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 06:57:45 +02:00
valknarandClaude Sonnet 4.6 4b99e21a99 feat: replace blinko with affine, route notifications to telegram
- Add AFFiNE stack (affine.pivoine.art): main app, migration job,
  redis, pgvector postgres
- Remove blinko stack
- Update backup.sh: swap blinko_db → affine_db
- Update README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 06:28:27 +02:00
valknarandClaude Sonnet 4.6 11ceb46e4a chore(backup): replace emoji codes with actual Unicode emojis
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 06:04:09 +02:00
valknarandClaude Sonnet 4.6 5985d8619f fix(backup): use message field in webhook payload, matching watchtower
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:36:16 +02:00
valknarandClaude Sonnet 4.6 eed45f1627 docs: update README — add notifications section for n8n/Telegram
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 22:30:40 +02:00
valknarandClaude Sonnet 4.6 39636e85c3 feat: replace mattermost with n8n, route notifications to telegram
- Add n8n stack (n8n.pivoine.art) with postgres, traefik, watchtower
- Remove mattermost stack entirely
- Update backup.sh: swap mattermost_db → n8n_db, rename
  MATTERMOST_WEBHOOK → WEBHOOK_URL, simplify notify() payload
- Update watchtower: mattermost:// → generic+https:// for n8n webhook
- Add _backup/.env.example
- Update README

Webhook URLs in _backup/.env and watchtower/.env contain
FILL_AFTER_N8N_SETUP — update once n8n workflow is created.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:36:58 +02:00
valknarandClaude Sonnet 4.6 5482236a9a chore(coolify): remove SSH config volume mounts
No longer needed after Coolify update — verified on VPS, container
stays healthy without them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 19:05:11 +02:00
valknarandClaude Sonnet 4.6 dc52de77bc feat(coolify): track SSH config and known_hosts in repo
Mount from stack directory instead of .data, consistent with how
gitea handles runner-config.yaml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 19:02:12 +02:00
valknarandClaude Sonnet 4.6 68bcea4adc fix(coolify): add SSH config volume mounts for Gitea integration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:59:59 +02:00
valknarandClaude Sonnet 4.6 f5b7f6f27e docs: update README — remove sexy stack, add .env.example setup step
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:56:55 +02:00
valknarandClaude Sonnet 4.6 28b31e91e4 chore: add .env.example files for all stacks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 18:55:30 +02:00
valknar 990ab0730a fix: no-index 2026-04-10 19:47:10 +02:00
valknar 1c8835bcf3 chore: cleanup 2026-03-30 17:47:34 +02:00
valknar 2750602fa5 chore: cleanup 2026-03-30 17:11:55 +02:00
valknar 3de764a055 chore: cleanup 2026-03-30 17:10:45 +02:00
valknar c5131580e4 chore: remove api 2026-03-27 09:54:38 +01:00
valknar 36da0dc752 fix: remove gemini 2026-03-20 17:19:02 +01:00
valknar 8364cdc65f chore: remove litellm docs 2026-03-18 20:16:54 +01:00
valknar 36fc4ee20a feat: add gemini-2.5-flash model to litellm 2026-03-18 18:43:44 +01:00
valknar 13956d7632 feat: add qwen3-coder model to litellm 2026-03-18 17:52:22 +01:00
valknar adfb6032ee chore: format 2026-03-18 17:39:36 +01:00
valknar cdb5a776be feat: add litellm 2026-03-18 17:39:19 +01:00
valknar 9e068eb7b3 style: customize gitea 2026-03-14 20:03:05 +01:00
valknar 74768a3ce5 chore: traefik without watchtower 2026-03-06 10:29:48 +01:00
valknar 1865844260 chore: cleanup 2026-03-05 09:51:40 +01:00
valknarandClaude Sonnet 4.6 491d54bbd5 fix: update sexy_db credentials to sexy:sexy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 21:53:00 +01:00
valknar f697eae0de fix: sexy directus image tag 2026-03-04 16:46:24 +01:00
valknar f427f408e0 feat: add blinko stack, remove joplin 2026-03-02 10:10:26 +01:00
valknar d0c38c1f46 fix: traefik image tag 2026-03-02 09:49:14 +01:00
valknar a22da351ed chore: umami tracking setup 2026-02-21 11:34:07 +01:00
valknar 0f10af0ca4 feat: palina ai image blog 2026-02-17 18:38:25 +01:00
valknar e555a78131 fix: use latest images 2026-02-17 12:23:09 +01:00
valknar 15f62b9e55 feat: Add realesrgan-api service to API stack 2026-02-16 20:22:33 +01:00
valknarandClaude Opus 4.6 4a09dce2c0 Add api stack with freepik and facefusion behind forwardAuth
Traefik routes api.pivoine.art/freepik and /facefusion to their
respective containers with path rewriting, shared API token auth
via an nginx sidecar, and api-rate-limit middleware.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 15:51:06 +01:00
valknarandClaude Opus 4.6 cd46be7d45 fix(sexy): add ASSETS_CACHE_TTL for long-lived browser caching
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 08:44:15 +01:00
valknarandClaude Opus 4.6 70462f4bd5 Fix umami DATABASE_URL to use container name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 08:09:57 +01:00
valknarandClaude Opus 4.6 755e5b5716 Update umami image to postgresql-latest
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 08:01:35 +01:00
valknarandClaude Opus 4.6 9c60f62422 Move restic repo path to .env and derive paths from script dir
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 07:19:35 +01:00
valknarandClaude Opus 4.6 d80d59fc2f Add restic backup stack with daily systemd timer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 07:14:32 +01:00
valknarandClaude Opus 4.6 e7bad9cbcb Add coolify network to traefik for Coolify container routing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 23:03:17 +01:00
valknarandClaude Opus 4.6 f21e0611b4 Add self-contained Docker Compose stacks for pivoine.art infrastructure
Migrated 11 services from monolithic docker-compose project into independent stacks,
each with dedicated databases, minimal .env configuration, and bind-mount data volumes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 22:41:50 +01:00