Commit Graph

91 Commits

Author SHA1 Message Date
9b433e66ad feat: add Vaultwarden password manager stack
Added self-hosted password manager to The Falcon infrastructure:

**Vault Stack** (vault.pivoine.art):
- Vaultwarden (Bitwarden-compatible server)
- SQLite database for password storage
- WebSocket support for real-time sync
- TOTP and WebAuthn/U2F 2FA support
- Browser extensions and mobile apps compatible

**Configuration:**
- Domain: https://vault.pivoine.art
- Signups: Disabled (invite-only for security)
- Invitations: Enabled
- Password hints: Disabled (security best practice)
- First user becomes admin

**Backup Integration:**
- Added vaultwarden-backup plan to Restic
- Schedule: 8 AM daily (same as letsencrypt)
- Retention: 7 daily, 4 weekly, 12 monthly, 3 yearly
- Backup volume: vault_data mounted read-only

**Infrastructure Updates:**
- Created vault/compose.yaml following stack pattern
- Added VAULT_* environment variables to arty.yml
- Updated compose.yaml to include vault stack
- Added backup_vaultwarden_data volume to restic
- Updated restic/config.json with 12th backup plan

**Documentation:**
- Added Vault to CORE SYSTEMS in README
- Added to ship architecture diagram
- Documented in CLAUDE.md with configuration details
- Updated volume management sections
- Backup count increased from 11 to 12 plans

Critical data backed up with long retention (3 years yearly).
Compatible with official Bitwarden clients on all platforms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 11:15:12 +01:00
fcfe508698 docs: document automated backup configuration
Updated documentation to reflect complete backup setup:

**CLAUDE.md Updates:**
- Added detailed repository configuration (hidrive-backup)
- Documented all 11 backup plans with schedules and retention
- Explained volume mounting strategy with prefixed names
- Added configuration management instructions
- Included maintenance schedule (weekly prune/check)

**README.md Updates:**
- Added "Backup Operations" section with CLI commands
- Documented automated backup schedule (2-8 AM daily)
- Added backup protocol to security section
- Updated mission status with backup system indicator
- Included next backup time and repository status

**compose.yaml Updates:**
- Restored backrest_config volume (needed for proper operation)
- Removed direct config.json mount (causes write conflicts)
- Config copied into volume after container start

All 11 backup plans now documented:
- postgres, redis, directus (uploads/bundle)
- awesome, gotify, scrapy, n8n
- filestash, linkwarden, letsencrypt

Retention policies range from 3-12 months with yearly backups
for critical data (postgres, directus, letsencrypt).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 10:40:28 +01:00
bed2106cfd fix: update Backrest config version to 4 for compatibility
Changed config version from 1 to 4 to match Backrest 1.10.1
requirements. Version 1 is too old and requires migration through
intermediate version 1.4.0.

Config now loads successfully with all 11 backup plans scheduled.
2025-11-06 10:34:09 +01:00
35ddcb2752 feat: add automated backup configuration for all volumes
Added comprehensive backup configuration to Backrest:

**Repository Configuration:**
- Target: /repos (mounted from /mnt/hidrive/users/valknar/Backup)
- Password: falcon-backup-2025
- Auto-initialize and auto-unlock enabled
- Weekly prune schedule (Sundays at 2 AM)
- Weekly integrity checks (Sundays at 3 AM)

**Backup Plans** (11 plans covering all volumes):
1. **postgres-backup** (2 AM daily)
   - PostgreSQL database
   - Retention: 7 daily, 4 weekly, 6 monthly, 2 yearly

2. **redis-backup** (3 AM daily)
   - Redis cache data
   - Retention: 7 daily, 4 weekly, 3 monthly

3. **directus-uploads-backup** (4 AM daily)
   - Directus media files
   - Retention: 7 daily, 4 weekly, 6 monthly, 2 yearly

4. **directus-bundle-backup** (4 AM daily)
   - Directus extensions
   - Retention: 7 daily, 4 weekly, 3 monthly

5. **awesome-backup** (5 AM daily)
   - Awesome app database
   - Retention: 7 daily, 4 weekly, 6 monthly

6. **gotify-backup** (5 AM daily)
   - Gotify notifications
   - Retention: 7 daily, 4 weekly, 3 monthly

7. **scrapy-backup** (6 AM daily)
   - Scrapyd data and spider code
   - Retention: 7 daily, 4 weekly, 3 monthly

8. **n8n-backup** (6 AM daily)
   - n8n workflow data
   - Retention: 7 daily, 4 weekly, 6 monthly

9. **filestash-backup** (7 AM daily)
   - Filestash state
   - Retention: 7 daily, 4 weekly, 3 monthly

10. **linkwarden-backup** (7 AM daily)
    - Linkwarden bookmarks and search index
    - Retention: 7 daily, 4 weekly, 6 monthly

11. **letsencrypt-backup** (8 AM daily)
    - SSL certificates
    - Retention: 7 daily, 4 weekly, 12 monthly, 3 yearly

**Configuration Mount:**
- config.json mounted directly at /config/config.json
- Read-write mode to allow UI updates
- Removed backrest_config volume (using file mount instead)

All backups scheduled at different times to spread I/O load.
Critical data (postgres, directus, letsencrypt) has longer retention.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 10:26:04 +01:00
acf6385aca fix: resolve volume name conflicts in restic stack
Prefixed all external volume references with 'backup_' to avoid
conflicts with volume definitions in other compose files (e.g.,
directus_uploads defined in both sexy and restic).

This allows Docker Compose's include pattern to work correctly
without volume name collisions.
2025-11-06 10:16:52 +01:00
c89769a23f feat: add Restic backup stack with Backrest UI
Added comprehensive backup solution to The Falcon infrastructure:

- **Restic Stack** (restic.pivoine.art):
  - Backrest web UI for managing restic backups
  - Automated scheduled backups with retention policies
  - Real-time backup status and monitoring
  - Restore capabilities via web interface

- **Backup Configuration**:
  - Target: /mnt/hidrive/users/valknar/Backup
  - Backs up all critical Docker volumes read-only:
    - PostgreSQL, Redis, Directus (uploads/bundle)
    - Awesome, Gotify, Scrapy (data/code)
    - n8n workflows, Filestash state
    - Linkwarden bookmarks/search index
    - Let's Encrypt SSL certificates

- **Infrastructure Updates**:
  - Added RESTIC_* environment variables to arty.yml
  - Updated compose.yaml to include restic stack
  - Updated README.md and CLAUDE.md documentation
  - Configured Traefik routing with SSL

All volumes mounted read-only to backup container for safety.
Backrest data persisted across: data, config, cache, tmp volumes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 10:13:07 +01:00
b14ff7a338 docs: update README with Traefik dashboard and Sablier integration
Updated THE FALCON documentation to reflect new infrastructure additions:

- **Traefik Dashboard**: Added proxy.pivoine.art to CORE SYSTEMS table as "Shield control dashboard"
- **Sablier Plugin**: Documented v1.10.1 plugin for dynamic scaling/scale-to-zero capabilities
- **Infrastructure Diagram**:
  - Added Dashboard Command Center to Traefik section
  - Added Sablier Dynamic Scaling Plugin
  - Updated SECURITY LAYER architecture with dashboard and Sablier entries

All systems operational and accessible via the Falcon network.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 09:30:36 +01:00
48335e13c0 fix: use latest tag for Sablier image instead of 1.10.1 2025-11-06 09:25:09 +01:00
632d63c85a feat: add Sablier v1.10.1 plugin for dynamic scaling
Added Sablier plugin and service for scale-to-zero capabilities:

**Traefik Plugin:**
- Added experimental.plugins.sablier configuration
- Plugin version: v1.10.1
- Module: github.com/acouvreur/sablier/plugins/traefik

**Sablier Service:**
- Created sablier/compose.yaml with Sablier server
- Uses Docker provider for container management
- Mounts Docker socket for container control
- Connected to falcon_network

**Configuration:**
- Added SABLIER_COMPOSE_PROJECT_NAME to arty.yml
- Added SABLIER_VERSION to arty.yml
- Included sablier stack in compose.yaml

**Usage:**
Services can now use Sablier middleware to automatically
scale to zero when idle and start on demand when accessed.

Example middleware configuration:
```yaml
http:
  middlewares:
    my-sablier:
      plugin:
        sablier:
          sablierUrl: http://sablier_app:10000
          names: service-name
          sessionDuration: 1m
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 09:23:20 +01:00
576036c86c fix: add port 8080 to Traefik dashboard service
Added loadbalancer.server.port=8080 to dashboard configuration
since the Traefik API/dashboard runs on port 8080 internally.

Also added ping endpoint for healthchecks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:46:13 +01:00
dae4c5f5f2 fix: streamline Traefik dashboard labels with HTTP redirect
Updated dashboard configuration to match the working pattern
from other services (Links, Scrapy, etc):

**Changes:**
- Added HTTP to HTTPS redirect middleware
- Added separate web and web-secure routers
- Renamed middleware from dashboard-auth to just auth
- Added explicit docker.network label
- Now follows the exact same pattern as Links stack

**Label Structure:**
- web router: HTTP entrypoint with redirect middleware
- web-secure router: HTTPS with TLS cert resolver and auth
- Consistent naming: proxy-web, proxy-web-secure, proxy-auth

This ensures the dashboard works the same way as all
other services in the stack.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:41:02 +01:00
d3850e559a refactor: use inline basicauth for Traefik dashboard
Changed dashboard authentication to use inline basicauth
like Scrapy instead of external .htpasswd file:

**Changes:**
- Updated proxy labels to use basicauth.users=${PROXY_AUTH_USERS}
- Removed .htpasswd file and auth directory
- Removed dashboard-auth middleware from security.yaml
- Removed .htpasswd volume mount from compose.yaml

**Benefits:**
- Consistent with Scrapy authentication pattern
- Simpler configuration (no external files)
- Auth credentials managed centrally via .env

Dashboard accessible at: https://proxy.pivoine.art
Credentials: valknar / ragnarok98 (via PROXY_AUTH_USERS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:35:43 +01:00
ec76db69ed feat: add Traefik dashboard at proxy.pivoine.art with basic auth
Added secure access to Traefik dashboard:

**Dashboard Configuration:**
- Enabled Traefik API and dashboard
- Configured router for proxy.pivoine.art
- Secured with HTTP Basic Auth middleware

**Security:**
- Created .htpasswd file with bcrypt credentials
- Added dashboard-auth middleware to dynamic/security.yaml
- Mounted .htpasswd file read-only in container
- Dashboard only accessible via HTTPS with valid credentials

**Environment Updates:**
- Added PROXY_AUTH_USERS to .env (htpasswd hash)
- Added PROXY_TRAEFIK_HOST to arty.yml

Dashboard accessible at: https://proxy.pivoine.art

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 08:17:42 +01:00
f5728b5f9c feat: add Linkwarden bookmark manager stack
Added new Links stack to Falcon infrastructure:

**Links Stack (links.pivoine.art):**
- Linkwarden bookmark manager with PostgreSQL backend
- Meilisearch v1.12.8 for full-text search
- Browser extension support
- Screenshot and PDF archiving
- Collaborative bookmark sharing

**Infrastructure Updates:**
- Created links/compose.yaml with linkwarden and meilisearch services
- Added linkwarden database to PostgreSQL init script
- Added LINKS_* environment variables to arty.yml
- Updated compose.yaml to include links stack
- Cleaned up .env to contain only secrets
- Added all EMAIL_* variables to .env

**Documentation:**
- Updated CLAUDE.md with Links service details
- Updated README.md with Links in CORE SYSTEMS table
- Added linkwarden_data and meili_data volumes to docs

**Required Secrets (in .env):**
- LINKS_NEXTAUTH_SECRET: NextAuth.js session encryption
- LINKS_MEILI_MASTER_KEY: Meilisearch API authentication

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 07:49:49 +01:00
0ffab37e99 fix: filestash url 2025-11-05 16:22:56 +01:00
0b839edd72 fix: update SCRAPYD_URL to point to /scrapyd path
Updated default SCRAPYD_URL from https://scrapy.pivoine.art to
https://scrapy.pivoine.art/scrapyd to match new routing
2025-11-05 06:43:42 +01:00
00739893ef feat: route scrapy-ui to root and scrapyd to /scrapyd
- scrapy.pivoine.art/ → scrapy-ui (main interface)
- scrapy.pivoine.art/scrapyd → scrapyd daemon
- Added router priorities to avoid conflicts
- Removed /ui prefix from scrapy-ui
2025-11-05 06:41:03 +01:00
321277de45 fix: restore stripprefix middleware for scrapy-ui
Next.js app doesn't have basePath configured, needs path stripping
2025-11-05 06:34:06 +01:00
16645f3ac0 test: remove stripprefix middleware from scrapy-ui 2025-11-05 06:26:29 +01:00
d94daedeef fix: use correct scrapy-ui image tag :main
Changed image tag from :latest to :main for ghcr.io/valknarness/scrapy-ui

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 06:16:49 +01:00
6df2de5bb2 feat: add Scrapy UI service with path-based routing
Added scrapy-ui service to scrapy stack:
- Image: ghcr.io/valknarness/scrapy-ui:latest
- Path-based routing: https://scrapy.pivoine.art/ui
- HTTP Basic Auth protection (same credentials as scrapyd)
- StripPrefix middleware to remove /ui from requests
- Auto-connects to scrapyd using SCRAPYD_URL, USERNAME, PASSWORD
- Watchtower auto-updates enabled

Traefik configuration:
- Middleware chain: auth -> stripprefix -> compress
- Routes /ui prefix to port 3000
- Shares authentication with main scrapyd interface

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-05 06:14:18 +01:00
b8bb380ea5 fix: remove SCRAPY_AUTH_USERS default from arty.yml
Removed default SCRAPY_AUTH_USERS value from arty.yml to ensure
credentials are only read from .env file (secrets).

This fixes login issues where the default placeholder value was
being used instead of actual credentials from .env.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 23:28:09 +01:00
3fea585782 docs: update documentation with security enhancements
Updated CLAUDE.md and README.md to document security features:

**CLAUDE.md updates:**
- Expanded Traefik section with security architecture details
- Added Security Configuration section with detailed guides
- Documented HTTP Basic Auth setup and credential management
- Added security testing commands and procedures
- Included TLS/header configuration instructions

**README.md updates:**
- Enhanced PROTOCOLS & SECURITY section
- Added TLS 1.2+ and cipher suite information
- Listed security headers (HSTS, X-Frame-Options, etc.)
- Documented HTTP Basic Auth and rate limiting
- Updated access control list

Documentation now reflects all security hardening applied to
Traefik reverse proxy and service authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 23:24:00 +01:00
b420f1d4bf feat: add comprehensive Traefik security hardening
Added security enhancements to Traefik reverse proxy:

**TLS Security:**
- Minimum TLS 1.2 enforced
- Strong cipher suites (ECDHE, AES-GCM, ChaCha20)
- Modern curve preferences (P-521, P-384)
- SNI strict mode enabled

**HTTP Security Headers:**
- HSTS with 1-year max-age, includeSubdomains, and preload
- X-Frame-Options: SAMEORIGIN (clickjacking protection)
- X-XSS-Protection enabled
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy (disable camera, mic, geolocation, etc.)
- X-Robots-Tag for SEO control

**Rate Limiting Middlewares:**
- General: 100 req/s average, 50 burst
- API endpoints: 30 req/s average, 15 burst

**Configuration:**
- Enabled Traefik file provider for dynamic config
- Security headers applied globally to web-secure entrypoint
- Dynamic config in proxy/dynamic/security.yaml
- Auto-reloads on config changes

All HTTPS traffic now benefits from enhanced security headers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 23:20:34 +01:00
b026878c38 feat: add HTTP Basic Auth to Scrapyd for security
Added Traefik Basic Auth middleware to secure Scrapyd web interface:
- Added basicauth middleware to scrapyd service labels
- Middleware chains auth with compression for HTTPS routes
- Added SCRAPY_AUTH_USERS environment variable to arty.yml
- Credentials stored in .env (htpasswd format with escaped $)

Access to scrapy.pivoine.art now requires username/password.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 23:17:13 +01:00
ef646eccfa fix: add scrapy_code named volume for scrapy and scrapyrt services
Both scrapy and scrapyrt services now use the shared scrapy_code named
volume instead of bind mounts. Code directory will be added later.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 22:43:55 +01:00
785942da61 feat: add Scrapy, n8n, and Filestash stacks to Falcon
Added three new service stacks to the docker-compose infrastructure:

- **Scrapy stack** (scrapy.pivoine.art):
  - scrapyd: Web scraping daemon with web interface (port 6800)
  - scrapy: Development container for spider commands
  - scrapyrt: Real-time API for running spiders (port 9080)

- **n8n stack** (n8n.pivoine.art):
  - Workflow automation platform with PostgreSQL backend
  - 200+ integrations for automated tasks
  - Runners enabled for task execution
  - Webhook support for external triggers

- **Filestash stack** (stash.pivoine.art):
  - Web-based file manager with multi-backend support
  - Supports SFTP, S3, Dropbox, Google Drive, FTP, WebDAV
  - In-browser file viewing and media playback

Infrastructure updates:
- Updated PostgreSQL init script to create n8n database
- Added environment variables to arty.yml for all three stacks
- Updated compose.yaml include list
- Updated CLAUDE.md and README.md documentation
- Normalized service names in existing stacks (gotify, proxy, umami, vpn)

All services integrated with Traefik for SSL termination and include
Watchtower auto-update labels.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-04 22:36:13 +01:00
816c24f86f feat: enable Watchtower auto-updates for awesome_app
Added watchtower.enable label to awesome_app container for automatic
Docker image updates when new versions are pushed to the registry.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 06:53:57 +01:00
b0dcafe9b5 feat: watch 2025-10-29 06:50:41 +01:00
9e7583c562 feat: add Watchtower for automatic Docker image updates
- Created watch/compose.yaml with Watchtower service configuration
- Added Watchtower environment variables to arty.yml
- Enabled Watchtower monitoring for sexy_frontend container
- Configurable via environment variables (poll interval, cleanup, logging)
- Label-based updates: only containers with watchtower.enable=true

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 06:40:32 +01:00
4e434378e6 chore: simplify database export/import scripts in arty.yml
- Remove dependency on .env file for database credentials
- Use direct database user and database name in scripts
- Update sexy/db/import to use correct credentials (valknar/directus)
- Remove artifact download step from awsm/import (not needed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 04:16:17 +01:00
e2518916cc chore: update Directus database with video-model associations
- Added video-to-model relationships in sexy_videos_directus_users junction table
- Updated sequence numbers for sexy_videos_directus_users and sexy_videos_models
- Fixed missing model associations for existing videos

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 04:15:33 +01:00
df78f3bfc3 refactor: apply env variable pattern to all sexy scripts
Extended environment variable usage to export scripts and simplified
the env loading pattern across all scripts.

Changes:
- sexy/db/export: now uses $DB_USER and $SEXY_DB_NAME
- sexy/export/all: now uses $DB_USER and $SEXY_DB_NAME
- All scripts: changed from 'set -a && source .env && set +a' to
  'export $(cat .env | xargs)' for cleaner, more concise syntax

This ensures consistent variable usage across all import/export scripts
and makes them work correctly in all environments.
2025-10-28 23:32:14 +01:00
4411698e9b fix: source .env file before executing import scripts
Added 'set -a && source .env && set +a' at the beginning of import scripts
to load environment variables from .env file.

This ensures DB_USER and SEXY_DB_NAME are properly set before executing
docker commands, regardless of whether arty exports them or not.

- set -a: enables automatic export of variables
- source .env: loads variables from .env file
- set +a: disables automatic export
2025-10-28 23:27:33 +01:00
6e47a85055 fix: use $VAR instead of ${VAR} for arty variable expansion
Changed from ${DB_USER}/${SEXY_DB_NAME} to $DB_USER/$SEXY_DB_NAME
for proper variable expansion in arty scripts.

Arty exports environment variables before executing scripts, so simple
$VAR syntax works correctly, while ${VAR} was being treated as literal
text in the shell context.
2025-10-28 23:26:57 +01:00
d3d9c7d0e2 fix: use hardcoded DB credentials for VPS production
Changed from ${DB_USER} and ${SEXY_DB_NAME} variables to hardcoded
values 'valknar' and 'directus' for production VPS environment.

Arty environment variables are not exported to the shell where scripts
execute, so the variables were empty when docker exec commands ran.

Production VPS always uses:
- PostgreSQL container: core_postgres
- DB user: valknar
- Database name: directus

These values are stable for production and won't change.
2025-10-28 23:26:12 +01:00
129a759795 fix: remove if/else from sexy/import/all to avoid arty syntax error
Removed interactive confirmation prompt (read -p and if/else/fi) from
sexy/import/all script. The if/else control structure caused syntax errors
when executed via arty due to how arty appends "$@" to scripts.

The script now runs directly without confirmation. Users should be careful
when running this destructive operation as it will immediately:
1. Drop and recreate all database tables
2. Apply Directus schema snapshot
3. Restart the Directus API

Warning message is still displayed before execution.
2025-10-28 23:24:36 +01:00
dee16f7321 fix: use environment variables in sexy import scripts
Changed hardcoded database credentials to use environment variables:
- `-U sexy` → `-U ${DB_USER}`
- `-d sexy` → `-d ${SEXY_DB_NAME}`

Also added missing interactive confirmation prompt to sexy/import/all script.

This fixes the script error on VPS where:
- VPS uses: DB_USER=valknar, SEXY_DB_NAME=directus
- Local dev uses: DB_USER=sexy, SEXY_DB_NAME=sexy (or directus)

The scripts now work correctly in both environments by reading
the appropriate values from .env files via arty's environment system.
2025-10-28 23:19:00 +01:00
c7608ae0b5 fix: scripts newline format 2025-10-28 23:13:19 +01:00
9c8be201ad refactor: standardize service naming and migrate track to umami
Service Naming Standardization:
- Renamed all compose service names to use consistent `{project}_app` pattern
- awsm: `awesome` → `awesome_app`
- gotify: `gotify` → `gotify_app` (also updated container_name)
- proxy: `traefik` → `traefik_app`
- vpn: `wg-easy` → `vpn_app`
- sexy: `directus` → `sexy_api`, `frontend` → `sexy_frontend`

Track to Umami Migration:
- Removed track/ directory (legacy naming)
- Created umami/ directory with updated compose.yaml
- Service now named `umami_app` following naming convention
- Configuration unchanged: PostgreSQL backend, Redis caching, Traefik routing
- Uses TRACK_* environment variables for compatibility with arty.yml

Benefits:
- Consistent naming makes service identification easier across projects
- Aligns with container_name conventions ({PROJECT}_app pattern)
- Improves docker ps readability and service management
- Umami directory name matches actual product name
2025-10-28 22:16:38 +01:00
960056cdf9 feat: add database and schema import scripts to arty.yml
Added three import scripts for sexy.pivoine.art database restoration:

1. sexy/db/import
   - Imports PostgreSQL database from directus.sql
   - Includes warning about destructive operation
   - Restarts Directus API after import

2. sexy/schema/import
   - Applies Directus schema snapshot from schema.yaml
   - Uses 'directus schema apply --yes'
   - Restarts Directus API after import

3. sexy/import/all
   - Combined import with interactive confirmation
   - Prompts user to type 'yes' to proceed
   - Imports database then applies schema
   - Complete restoration workflow

All scripts include comprehensive comments and safety warnings.
Complements existing export scripts (sexy/db/export, sexy/schema/export, sexy/export/all).

Usage:
  pnpm arty sexy/db/import       # Import database only
  pnpm arty sexy/schema/import   # Import schema only
  pnpm arty sexy/import/all      # Full import (with confirmation)
2025-10-28 22:12:25 +01:00
36f48de7ad feat: update database and add Directus schema snapshot
Database Changes (directus.sql):
- Updated with complete gamification system (5 new tables)
- Added original_recording_id field to sexy_recordings for tracking duplicates
- Changed sexy_recordings.duration to NUMERIC(10,2) for decimal milliseconds
- Changed sexy_recordings.tags from text[] to json type
- All 17 achievements seeded (recordings, playback, social, special)
- Includes DROP IF EXISTS statements for safe re-imports
- Flags used: --clean --if-exists --no-owner --no-acl

New File - Directus Schema (schema.yaml):
- Complete Directus v11.12.0 schema snapshot
- All collections, fields, relations, and metadata
- Custom collections: sexy_recordings, sexy_videos, sexy_achievements, etc.
- Gamification tables: sexy_user_points, sexy_user_stats, sexy_user_achievements
- Can be applied with: npx directus schema apply schema.yaml

Export Command:
  docker exec sexy_postgres pg_dump -U sexy -d sexy \
    --no-owner --no-acl --clean --if-exists > directus.sql

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 21:51:14 +01:00
c682494289 fix: directus db revert 2025-10-28 21:35:41 +01:00
800c59ff94 feat: directus scheme 2025-10-28 21:24:34 +01:00
7949366477 feat: directus scheme 2025-10-28 21:10:26 +01:00
5c0b97e180 feat: update database dump with complete gamification system
- Added 5 new tables:
  - sexy_user_points: Point tracking history
  - sexy_achievements: Achievement definitions (17 seeded)
  - sexy_user_achievements: User achievement unlocks
  - sexy_user_stats: Aggregated user statistics and rankings
  - sexy_recording_plays: Playback tracking for gamification

- Updated sexy_recordings schema:
  - duration: INTEGER → NUMERIC(10,2) for decimal milliseconds
  - tags: text[] → json for consistent array handling

- Seeded 17 achievements across categories:
  - Recordings: First Recording, Recording Enthusiast, Prolific Creator, etc.
  - Playback: First Play, Active Player, Completionist
  - Social: First Comment, Conversationalist, Community Voice
  - Special: Early Adopter, Top 10 Rank, Balanced Creator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 14:07:04 +01:00
b8467dda54 fix: change sexy_recordings duration to numeric type
Change duration column from integer to numeric(10,2) to support
decimal values in milliseconds. Fixes error when saving recordings
with fractional durations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 13:41:16 +01:00
3dcd76f35a feat: update database dump with gamification tables
Add gamification system tables to database dump:
- sexy_user_points: Point transaction log
- sexy_achievements: Achievement definitions (17 seeded)
- sexy_user_achievements: User achievement progress
- sexy_user_stats: Cached user statistics for leaderboard
- sexy_recording_plays: Recording playback tracking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 13:37:23 +01:00
e845ad2625 feat: add sexy_recordings table to database schema
Added missing sexy_recordings table which stores hardware device session recordings. This table is required for the /me dashboard page to load properly.

Table structure:
- id, title, description, slug (unique)
- duration (integer), events (JSONB), device_info (JSONB)
- tags (text array), linked_video (foreign key to sexy_videos)
- status (draft/published/archived), public flag
- user_created/updated, date_created/updated
- Indexes on user_created, status, slug, linked_video, tags (GIN)

This fixes the 5-minute timeout issue on /me page where the recordings endpoint was trying to access a non-existent table.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 12:31:53 +01:00
c4a84ff0fb feat: add missing junction tables for models and videos
Added sexy_model_photos and sexy_videos_models junction tables to support
many-to-many relationships between models/files and videos/models.

This resolves 500 errors on homepage and endpoints that were querying
these missing tables.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 12:09:35 +01:00