HEIC handling
- pillow-heif joins the deps; app/lib/transcode.py registers the
HEIF opener and exposes heic_to_jpeg(bytes, quality=88) with EXIF
rotation applied so portrait iPhone photos do not show sideways.
- Storage gains get_bytes / put_bytes so the server can read the
uploaded HEIC out of MinIO, decode it, and put a JPEG back.
- /api/uploads/{id}/confirm now runs the transcode after the HEAD
check passes when mime_type is image/heic or image/heif: writes
the JPEG under a sibling key, deletes the HEIC, and updates the
upload row's storage_key / mime_type / size_bytes. Failures fall
back to keeping the HEIC so an upload is never lost in transit;
the admin can re-upload if a particular file is unrenderable.
Backups (two sidecars in docker-compose.yml)
- postgres-backup uses prodrigestivill/postgres-backup-local:16-alpine
with BACKUP_SCHEDULE_DB (default @daily) and layered retention
(days/weeks/months) writing to ./backups/postgres on the host.
- media-backup is an alpine container that pulls mc on boot, sets up
an alias for the in-cluster MinIO, optionally adds a remote alias
(R2/B2/S3 via BACKUP_REMOTE_*), and runs mc mirror on a configurable
cron schedule. Local mirror always; remote mirror only when
BACKUP_REMOTE_* are set.
- Both write to ./backups/ on the host (bind mount), so the operator
can rsync the directory off-box without touching containers.
- .env.example documents every new variable, including a R2 example
for the remote target, and TZ for cron alignment.
Local backups directory is .gitignore'd so accidental commits do not
ship someone else's wedding photos to GitHub.
58 lines
2.2 KiB
Plaintext
58 lines
2.2 KiB
Plaintext
# =============================================================================
|
|
# Edite essas variáveis e salve como .env (mesmo diretório do docker-compose.yml)
|
|
# =============================================================================
|
|
|
|
# ----- Domínios (apontar DNS A/AAAA pra IP do VPS antes do `docker compose up`)
|
|
DOMAIN=casamento.exemplo.com.br
|
|
MEDIA_DOMAIN=midia.exemplo.com.br
|
|
ACME_EMAIL=voce@exemplo.com
|
|
|
|
# ----- Postgres
|
|
POSTGRES_USER=wedding
|
|
POSTGRES_PASSWORD=troque-isso-por-uma-senha-forte
|
|
POSTGRES_DB=wedding
|
|
|
|
# ----- MinIO (root credentials = também usadas pelo app como S3 access keys)
|
|
MINIO_ROOT_USER=minioadmin
|
|
MINIO_ROOT_PASSWORD=troque-isso-por-uma-senha-forte
|
|
S3_BUCKET=wedding-media
|
|
S3_REGION=us-east-1
|
|
# Endpoint INTERNO usado pelo app pra falar com o MinIO. Use o do Caddy
|
|
# (https://${MEDIA_DOMAIN}) — necessário porque a assinatura S3 inclui o host
|
|
# e o browser faz upload direto pra MEDIA_DOMAIN. Hairpin via DNS público é OK.
|
|
# Pra evitar hairpin, ajuste extra_hosts no compose pra resolver MEDIA_DOMAIN
|
|
# pra IP interno e set S3_INTERNAL_ENDPOINT=http://minio:9000 (avançado).
|
|
S3_INTERNAL_ENDPOINT=
|
|
|
|
# ----- App
|
|
COUPLE_NAMES=Stefanie & Leandro
|
|
EVENT_DATE=07 de junho de 2026
|
|
|
|
# ----- Admin (painel dos noivos)
|
|
ADMIN_PASSWORD=senha-forte-compartilhada-entre-os-dois
|
|
SESSION_SECRET=gere-um-uuid-longo-aqui-min-32-chars
|
|
ALLOWED_ADMIN_EMAILS=voce@exemplo.com,outro@exemplo.com
|
|
|
|
# ----- Backup (vai pra ./backups/ no host por padrão)
|
|
TZ=America/Sao_Paulo
|
|
# Cron schedule para o Postgres: aceita formato cron OR @daily/@hourly/etc
|
|
BACKUP_SCHEDULE_DB=@daily
|
|
# Cron para o MinIO (mc mirror é incremental, pode rodar mais vezes)
|
|
BACKUP_SCHEDULE_MEDIA=0 3 * * *
|
|
# Retenção (camadas: dias / semanas / meses) — só pro Postgres
|
|
BACKUP_KEEP_DAYS=14
|
|
BACKUP_KEEP_WEEKS=4
|
|
BACKUP_KEEP_MONTHS=6
|
|
|
|
# Backup remoto OPCIONAL — espelha o bucket pra outro provedor S3 (R2,
|
|
# B2, AWS S3, outro MinIO). Deixe vazio pra ficar só com backup local.
|
|
# Exemplo com Cloudflare R2:
|
|
# BACKUP_REMOTE_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
|
|
# BACKUP_REMOTE_ACCESS_KEY=...
|
|
# BACKUP_REMOTE_SECRET_KEY=...
|
|
# BACKUP_REMOTE_BUCKET=wedding-media-backup
|
|
BACKUP_REMOTE_ENDPOINT=
|
|
BACKUP_REMOTE_ACCESS_KEY=
|
|
BACKUP_REMOTE_SECRET_KEY=
|
|
BACKUP_REMOTE_BUCKET=
|