- Fork elmeg-demo codebase for multi-band support - Add data importer infrastructure with base class - Create band-specific importers: - phish.py: Phish.net API v5 - grateful_dead.py: Grateful Stats API - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm) - Add spec-kit configuration for Gemini - Update README with supported bands and architecture
4 KiB
Infrastructure Standards & Best Practices
Overview
This document outlines the standardized infrastructure patterns and best practices for the Elmeg and Ersen ecosystem. It is intended for future agents and developers to ensure consistency and avoid common pitfalls during deployment and configuration.
1. Routing & Load Balancing (Traefik)
Architecture
The production server (tangible-aacorn) uses Traefik as the reverse proxy and load balancer. Unlike standard Docker deployments that often rely solely on container labels, this environment uses a hybrid approach with a strong preference for static configuration files for critical routing.
Critical Anti-Pattern: Docker Labels vs. Static Routes
Important
Do not rely solely on
docker-compose.ymllabels for routing public traffic on the production server.While the Traefik Docker provider is enabled, the primary routing logic for
ersen.xyz,elmeg.xyz, and their subdomains is managed via a centralized static routes file. Relying only on labels can lead to 404s if the static configuration takes precedence or if the Docker socket connection is flaky.
Standard Procedure: Adding a New Subdomain
To expose a new service (e.g., stats.elmeg.xyz), you must:
- Define the Service in Docker: Ensure your container exposes the correct port internally (e.g.,
3000). - Update the Central Routes File:
- File Path:
/srv/containers/ersen/traefik-routes.yml(ontangible-aacorn) - Action: Add a new
RouterandServicedefinition.
- File Path:
Example Configuration (traefik-routes.yml)
http:
routers:
# ... existing routers ...
my-new-service-router:
rule: "Host(`new.elmeg.xyz`)"
service: my-new-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
# ... existing services ...
my-new-service:
loadBalancer:
servers:
- url: "http://container-name:port"
- Reloading: Traefik is configured to watch this file (
--providers.file.watch=true), so changes should apply automatically. If not, restart the Traefik container.
2. Deployment Standards
Directory Structure
All services reside in /srv/containers/.
- Repo Root:
/srv/containers/<project-name>(e.g.,/srv/containers/elmeg-demo) - Ownership: All files must be owned by the
deployuser.- Fix command:
sudo chown -R deploy:deploy /srv/containers/<project-name>
- Fix command:
Git-Based Deployment
We use a Pull-based workflow on the server:
-
Commit & Push changes to the remote configuration (Forgejo).
-
SSH into Server:
ssh tangible-aacorn -
Pull & Restart:
cd /srv/containers/<project-name> git pull docker compose up -d --build <service-name>
Docker Compose
- Version: Use
servicestop-level key. Avoid the deprecatedversion: '3.x'line in new files. - Networking:
- Services sharing the same proxy must be on the same external network (usually
ersern_traefik-publicortraefik). - Define this network as
external: trueat the bottom ofdocker-compose.yml.
- Services sharing the same proxy must be on the same external network (usually
3. Environment Variables
- Production: Use a
.envfile in the project root on the server. - Security: Never commit
.envfiles to the repository. - Variables:
- DATABASE_URL: Full connection string for Prisma/Postgres.
- INTERNAL_API_URL: Used for SSR (Server-Side Rendering) to talk to the backend within the Docker network.
- NEXT_PUBLIC_API_URL: Used for the client-side browser to talk to the backend (via public URL).
4. Troubleshooting Checklist
If a service is returning 404:
- Check DNS: Is the subdomain pointing to the server IP?
- Check Traefik Logs:
docker logs ersen-traefik-1 --tail 50 - Verify Routes File: Cat the
traefik-routes.ymlto see if your route exists. - Verify Network: Inspect the service container to ensure it's connected to the
traefiknetwork.