diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..26ce58a --- /dev/null +++ b/.env.example @@ -0,0 +1,75 @@ +#See more informations here : https://doc.getlago.com/guide/self-hosted/docker + +LAGO_VERSION=v1.13.1 + +# PostgreSQL Configuration +POSTGRES_DB=lago +POSTGRES_USER=lago +POSTGRES_PASSWORD=changeme +POSTGRES_HOST=db +POSTGRES_PORT=5432 +POSTGRES_SCHEMA=public +PGDATA=/data/postgres + +# Redis Configuration +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_PASSWORD= + +# Application Ports +API_PORT=3000 +FRONT_PORT=80 + + +# Lago Global Configuration +LAGO_DOMAIN=yourdomain.told +LAGO_API_URL=https://yourdomain.tld/api +LAGO_FRONT_URL=https://yourdomain.tld +SECRET_KEY_BASE=your-secret-key-base-hex-64 +RAILS_ENV=production +LAGO_RAILS_STDOUT=true +LAGO_PDF_URL=http://pdf:3000 +LAGO_DISABLE_SIGNUP=false +APP_ENV=production + +# Encryption Keys +LAGO_RSA_PRIVATE_KEY= +LAGO_ENCRYPTION_PRIMARY_KEY=your-encryption-primary-key +LAGO_ENCRYPTION_DETERMINISTIC_KEY=your-encryption-deterministic-key +LAGO_ENCRYPTION_KEY_DERIVATION_SALT=your-encryption-derivation-salt + +# AWS S3 Configuration +LAGO_USE_AWS_S3=false +LAGO_AWS_S3_ACCESS_KEY_ID=azerty123456 +LAGO_AWS_S3_SECRET_ACCESS_KEY=azerty123456 +LAGO_AWS_S3_REGION=us-east-1 +LAGO_AWS_S3_BUCKET=bucket +LAGO_AWS_S3_ENDPOINT= + +# Google Cloud Storage Configuration +LAGO_USE_GCS=false +LAGO_GCS_PROJECT= +LAGO_GCS_BUCKET= + +# Redis Cache Configuration +LAGO_REDIS_CACHE_HOST=redis +LAGO_REDIS_CACHE_PORT=6379 +LAGO_REDIS_CACHE_PASSWORD= + +# Sentry Configuration +SENTRY_DSN= +SENTRY_DSN_FRONT= + +# Lago Feature Flags +LAGO_DISABLE_SEGMENT= +LAGO_DISABLE_WALLET_REFRESH= +LAGO_SIDEKIQ_WEB= +SIDEKIQ_EVENTS= +SIDEKIQ_PDFS= + +# OAuth and Authentication +LAGO_OAUTH_PROXY_URL=https://proxy.getlago.com +GOOGLE_AUTH_CLIENT_ID= +GOOGLE_AUTH_CLIENT_SECRET= +NANGO_SECRET_KEY= +LAGO_LICENSE= diff --git a/docker-compose.new.yml b/docker-compose.new.yml new file mode 100644 index 0000000..3db732e --- /dev/null +++ b/docker-compose.new.yml @@ -0,0 +1,301 @@ +volumes: + lago_postgres_data: + lago_redis_data: + lago_storage_data: + traefik_certificates: + traefik_config: + +x-common-environment: &common-environment + LAGO_API_URL: ${LAGO_API_URL} + REDIS_PASSWORD: ${REDIS_PASSWORD} + SECRET_KEY_BASE: ${SECRET_KEY_BASE} + RAILS_ENV: ${RAILS_ENV} + RAILS_LOG_TO_STDOUT: ${LAGO_RAILS_STDOUT} + SENTRY_DSN: ${SENTRY_DSN} + LAGO_FRONT_URL: ${LAGO_FRONT_URL} + LAGO_RSA_PRIVATE_KEY: ${LAGO_RSA_PRIVATE_KEY} + LAGO_ENCRYPTION_PRIMARY_KEY: ${LAGO_ENCRYPTION_PRIMARY_KEY} + LAGO_ENCRYPTION_DETERMINISTIC_KEY: ${LAGO_ENCRYPTION_DETERMINISTIC_KEY} + LAGO_ENCRYPTION_KEY_DERIVATION_SALT: ${LAGO_ENCRYPTION_KEY_DERIVATION_SALT} + LAGO_USE_AWS_S3: ${LAGO_USE_AWS_S3} + LAGO_AWS_S3_ACCESS_KEY_ID: ${LAGO_AWS_S3_ACCESS_KEY_ID} + LAGO_AWS_S3_SECRET_ACCESS_KEY: ${LAGO_AWS_S3_SECRET_ACCESS_KEY} + LAGO_AWS_S3_REGION: ${LAGO_AWS_S3_REGION} + LAGO_AWS_S3_BUCKET: ${LAGO_AWS_S3_BUCKET} + LAGO_AWS_S3_ENDPOINT: ${LAGO_AWS_S3_ENDPOINT} + LAGO_USE_GCS: ${LAGO_USE_GCS} + LAGO_GCS_PROJECT: ${LAGO_GCS_PROJECT} + LAGO_GCS_BUCKET: ${LAGO_GCS_BUCKET} + LAGO_PDF_URL: ${LAGO_PDF_URL} + LAGO_REDIS_CACHE_PASSWORD: ${LAGO_REDIS_CACHE_PASSWORD} + LAGO_DISABLE_SEGMENT: ${LAGO_DISABLE_SEGMENT} + LAGO_DISABLE_WALLET_REFRESH: ${LAGO_DISABLE_WALLET_REFRESH} + NANGO_SECRET_KEY: ${NANGO_SECRET_KEY} + LAGO_LICENSE: ${LAGO_LICENSE} + +x-api-environment: &api-environment + <<: *common-environment + LAGO_SIDEKIQ_WEB: ${LAGO_SIDEKIQ_WEB} + LAGO_OAUTH_PROXY_URL: ${LAGO_OAUTH_PROXY_URL} + GOOGLE_AUTH_CLIENT_ID: ${GOOGLE_AUTH_CLIENT_ID} + GOOGLE_AUTH_CLIENT_SECRET: ${GOOGLE_AUTH_CLIENT_SECRET} + +x-front-environment: &front-environment + API_URL: ${LAGO_API_URL} + APP_ENV: ${APP_ENV} + LAGO_DISABLE_SIGNUP: ${LAGO_DISABLE_SIGNUP} + LAGO_OAUTH_PROXY_URL: ${LAGO_OAUTH_PROXY_URL} + SENTRY_DSN: ${SENTRY_DSN_FRONT} + NANGO_SECRET_KEY: ${NANGO_SECRET_KEY} + +services: + traefik: + image: traefik:v2.5 + container_name: traefik + restart: unless-stopped + command: + - "--api.insecure=false" + - "--api.dashboard=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--certificatesresolvers.lagoresolver.acme.tlschallenge=true" + - "--certificatesresolvers.lagoresolver.acme.email=youremail@lagoddomain.tld" + - "--certificatesresolvers.lagoresolver.acme.storage=/letsencrypt/acme.json" + ports: + - "80:80" + - "443:443" + volumes: + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - traefik_certificates:/letsencrypt + - traefik_config:/traefik + labels: + - "traefik.http.routers.traefik.rule=Host(`traefik.${LAGO_DOMAIN}`)" + - "traefik.http.routers.traefik.entrypoints=websecure" + - "traefik.http.routers.traefik.tls.certresolver=lagoresolver" + - "traefik.http.services.traefik.loadbalancer.server.port=8080" + + api: + container_name: lago-api + image: getlago/api:${LAGO_VERSION} + restart: unless-stopped + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + command: ['./scripts/start.sh'] + environment: + <<: *api-environment + DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=${POSTGRES_SCHEMA}" + REDIS_URL: "redis://${REDIS_HOST}:${REDIS_PORT:-6379}" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 10s + timeout: 60s + retries: 5 + labels: + - "traefik.enable=true" + - "traefik.http.routers.api.entrypoints=websecure" + - "traefik.http.routers.api.rule=Host(`${LAGO_DOMAIN}`) && PathPrefix(`/api`)" + - "traefik.http.routers.api.tls.certresolver=lagoresolver" + - "traefik.http.routers.api.priority=100" + - "traefik.http.services.api.loadbalancer.server.port=3000" + - "traefik.http.middlewares.api-strip-prefix.stripprefix.prefixes=/api" + - "traefik.http.routers.api.middlewares=api-strip-prefix" + volumes: + - lago_storage_data:/app/storage + + front: + container_name: lago-front + image: getlago/front:${LAGO_VERSION} + restart: unless-stopped + depends_on: + api: + condition: service_healthy + environment: + <<: *front-environment + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80"] + interval: 30s + timeout: 10s + retries: 3 + labels: + - "traefik.http.routers.front.priority=50" + - "traefik.enable=true" + - "traefik.http.routers.front.entrypoints=websecure" + - "traefik.http.routers.front.rule=Host(`${LAGO_DOMAIN}`) && PathPrefix(`/`)" + - "traefik.http.routers.front.tls.certresolver=lagoresolver" + - "traefik.http.services.front.loadbalancer.server.port=80" + volumes: + - lago_storage_data:/app/storage + + db: + image: postgres:14-alpine + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PGDATA: ${PGDATA} + PGPORT: ${POSTGRES_PORT} + POSTGRES_SCHEMA: ${POSTGRES_SCHEMA} + volumes: + - lago_postgres_data:/data/postgres + ports: + - "${POSTGRES_PORT}:${POSTGRES_PORT}" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:6-alpine + container_name: lago-redis + restart: unless-stopped + command: --port ${REDIS_PORT:-6379} + volumes: + - lago_redis_data:/data + ports: + - "${REDIS_PORT:-6379}:${REDIS_PORT:-6379}" + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + api-worker: + container_name: lago-worker + image: getlago/api:${LAGO_VERSION} + restart: unless-stopped + depends_on: + api: + condition: service_healthy + command: ['./scripts/start.worker.sh'] + environment: + <<: *common-environment + LAGO_REDIS_CACHE_URL: "redis://${LAGO_REDIS_CACHE_HOST}:${LAGO_REDIS_CACHE_PORT}" + DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=${POSTGRES_SCHEMA}" + REDIS_URL: "redis://${REDIS_HOST}:${REDIS_PORT:-6379}" + healthcheck: + test: ['CMD-SHELL', 'bundle exec sidekiqmon | grep $(hostname) || exit 1'] + volumes: + - lago_storage_data:/app/storage + + + api-clock: + container_name: lago-clock + image: getlago/api:${LAGO_VERSION} + restart: unless-stopped + depends_on: + api: + condition: service_healthy + command: ['./scripts/start.clock.sh'] + environment: + <<: *common-environment + LAGO_REDIS_CACHE_URL: "redis://${LAGO_REDIS_CACHE_HOST}:${LAGO_REDIS_CACHE_PORT}" + DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=${POSTGRES_SCHEMA}" + REDIS_URL: "redis://${REDIS_HOST}:${REDIS_PORT:-6379}" + + pdf: + image: getlago/lago-gotenberg:7.8.2 + + migrate: + container_name: lago-migrate + image: getlago/api:${LAGO_VERSION} + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + command: ['./scripts/start.migrate.sh'] + volumes: + - lago_storage_data:/app/storage + + # You can uncomment this if you want to use a dedicated Sidekiq worker for the event ingestion. + # It is recommendend if you have a high usage of events to not impact the other Sidekiq Jobs. + #api-events-worker: + # container_name: lago-events-worker + # image: getlago/api:${LAGO_VERSION} + # restart: unless-stopped + # depends_on: + # api: + # condition: service_healthy + # command: ["./scripts/start.events.worker.sh"] + # environment: + # - LAGO_API_URL=${LAGO_API_URL:-http://localhost:3000} + # - DATABASE_URL=postgresql://${POSTGRES_USER:-lago}:${POSTGRES_PASSWORD:-changeme}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-lago}?search_path=${POSTGRES_SCHEMA:-public} + # - REDIS_URL=redis://${REDIS_HOST:-redis}:${REDIS_PORT:-6379} + # - REDIS_PASSWORD=${REDIS_PASSWORD} + # - SECRET_KEY_BASE=${SECRET_KEY_BASE:-your-secret-key-base-hex-64} + # - RAILS_ENV=production + # - RAILS_LOG_TO_STDOUT=${LAGO_RAILS_STDOUT:-true} + # - SENTRY_DSN=${SENTRY_DSN} + # - LAGO_RSA_PRIVATE_KEY=${LAGO_RSA_PRIVATE_KEY} # Should be base64 encoded + # - RSA_PRIVATE_KEY=${LAGO_RSA_PRIVATE_KEY} # Should be base64 encoded + # - LAGO_ENCRYPTION_PRIMARY_KEY=${LAGO_ENCRYPTION_PRIMARY_KEY:-your-encryption-primary-key} + # - LAGO_ENCRYPTION_DETERMINISTIC_KEY=${LAGO_ENCRYPTION_DETERMINISTIC_KEY:-your-encryption-deterministic-key} + # - LAGO_ENCRYPTION_KEY_DERIVATION_SALT=${LAGO_ENCRYPTION_KEY_DERIVATION_SALT:-your-encryption-derivation-salt} + # - LAGO_FRONT_URL=${LAGO_FRONT_URL:-http://localhost} + # - LAGO_USE_AWS_S3=${LAGO_USE_AWS_S3:-false} + # - LAGO_AWS_S3_ACCESS_KEY_ID=${LAGO_AWS_S3_ACCESS_KEY_ID:-azerty123456} + # - LAGO_AWS_S3_SECRET_ACCESS_KEY=${LAGO_AWS_S3_SECRET_ACCESS_KEY:-azerty123456} + # - LAGO_AWS_S3_REGION=${LAGO_AWS_S3_REGION:-us-east-1} + # - LAGO_AWS_S3_BUCKET=${LAGO_AWS_S3_BUCKET:-bucket} + # - LAGO_AWS_S3_ENDPOINT=${LAGO_AWS_S3_ENDPOINT} + # - LAGO_USE_GCS=${LAGO_USE_GCS:-false} + # - LAGO_GCS_PROJECT=${LAGO_GCS_PROJECT:-} + # - LAGO_GCS_BUCKET=${LAGO_GCS_BUCKET:-} + # - LAGO_PDF_URL=${LAGO_PDF_URL:-http://pdf:3000} + # - LAGO_REDIS_CACHE_URL=redis://${LAGO_REDIS_CACHE_HOST:-redis}:${LAGO_REDIS_CACHE_PORT:-6379} + # - LAGO_REDIS_CACHE_PASSWORD=${LAGO_REDIS_CACHE_PASSWORD} + # - LAGO_DISABLE_SEGMENT=${LAGO_DISABLE_SEGMENT} + # - LAGO_DISABLE_WALLET_REFRESH=${LAGO_DISABLE_WALLET_REFRESH} + # - NANGO_SECRET_KEY=${NANGO_SECRET_KEY:-} + # - SIDEKIQ_EVENTS=true + # - LAGO_LICENSE=${LAGO_LICENSE:-} + + # You can uncomment this if you want to use a dedicated Sidekiq worker for the invoices pdf creation. + # It is recommended if you have a high usage of invoices being created to not impact the other Sidekiq Jobs. + #api-pdfs-worker: + # container_name: lago-pdfs-worker + # image: getlago/api:${LAGO_VERSION} + # restart: unless-stopped + # depends_on: + # api: + # condition: service_healthy + # command: ["./scripts/start.pdfs.worker.sh"] + # environment: + # - LAGO_API_URL=${LAGO_API_URL:-http://localhost:3000} + # - DATABASE_URL=postgresql://${POSTGRES_USER:-lago}:${POSTGRES_PASSWORD:-changeme}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-lago}?search_path=${POSTGRES_SCHEMA:-public} + # - REDIS_URL=redis://${REDIS_HOST:-redis}:${REDIS_PORT:-6379} + # - REDIS_PASSWORD=${REDIS_PASSWORD} + # - SECRET_KEY_BASE=${SECRET_KEY_BASE:-your-secret-key-base-hex-64} + # - RAILS_ENV=production + # - RAILS_LOG_TO_STDOUT=${LAGO_RAILS_STDOUT:-true} + # - SENTRY_DSN=${SENTRY_DSN} + # - LAGO_RSA_PRIVATE_KEY=${LAGO_RSA_PRIVATE_KEY} # Should be base64 encoded + # - RSA_PRIVATE_KEY=${LAGO_RSA_PRIVATE_KEY} # Should be base64 encoded + # - LAGO_ENCRYPTION_PRIMARY_KEY=${LAGO_ENCRYPTION_PRIMARY_KEY:-your-encryption-primary-key} + # - LAGO_ENCRYPTION_DETERMINISTIC_KEY=${LAGO_ENCRYPTION_DETERMINISTIC_KEY:-your-encryption-deterministic-key} + # - LAGO_ENCRYPTION_KEY_DERIVATION_SALT=${LAGO_ENCRYPTION_KEY_DERIVATION_SALT:-your-encryption-derivation-salt} + # - LAGO_FRONT_URL=${LAGO_FRONT_URL:-http://localhost} + # - LAGO_USE_AWS_S3=${LAGO_USE_AWS_S3:-false} + # - LAGO_AWS_S3_ACCESS_KEY_ID=${LAGO_AWS_S3_ACCESS_KEY_ID:-azerty123456} + # - LAGO_AWS_S3_SECRET_ACCESS_KEY=${LAGO_AWS_S3_SECRET_ACCESS_KEY:-azerty123456} + # - LAGO_AWS_S3_REGION=${LAGO_AWS_S3_REGION:-us-east-1} + # - LAGO_AWS_S3_BUCKET=${LAGO_AWS_S3_BUCKET:-bucket} + # - LAGO_AWS_S3_ENDPOINT=${LAGO_AWS_S3_ENDPOINT} + # - LAGO_USE_GCS=${LAGO_USE_GCS:-false} + # - LAGO_GCS_PROJECT=${LAGO_GCS_PROJECT:-} + # - LAGO_GCS_BUCKET=${LAGO_GCS_BUCKET:-} + # - LAGO_PDF_URL=${LAGO_PDF_URL:-http://pdf:3000} + # - LAGO_REDIS_CACHE_URL=redis://${LAGO_REDIS_CACHE_HOST:-redis}:${LAGO_REDIS_CACHE_PORT:-6379} + # - LAGO_REDIS_CACHE_PASSWORD=${LAGO_REDIS_CACHE_PASSWORD} + # - LAGO_DISABLE_SEGMENT=${LAGO_DISABLE_SEGMENT} + # - LAGO_DISABLE_WALLET_REFRESH=${LAGO_DISABLE_WALLET_REFRESH} + # - NANGO_SECRET_KEY=${NANGO_SECRET_KEY:-} + # - SIDEKIQ_PDFS=true + # - LAGO_LICENSE=${LAGO_LICENSE:-} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.old.yml similarity index 88% rename from docker-compose.yml rename to docker-compose.old.yml index 490774b..7b31ac5 100644 --- a/docker-compose.yml +++ b/docker-compose.old.yml @@ -1,3 +1,39 @@ +############################################################ +# # +# !!! WARNING !!! # +# # +# This file 'docker-compose.old.yaml' is DEPRECATED # +# and will be permanently removed from the repository # +# on January 1st, 2025. The 'docker-compose.new.yaml' # +# will then become 'docker-compose.yaml'. # +# # +# Please migrate to the new version by following # +# the steps below: # +# # +# 1. Perform a backup of the current volumes. # +# This step is mandatory! # +# # +# 2. Most variables will be set in the '.env' file # +# (see '.env.example' for more information). # +# # +# 3. Change the 'apiUrl' variable, which no longer # +# uses 'api.', but now ends with '/api' after # +# the domain name. # +# # +# 4. SSL certificate management is now automatic. # +# There's nothing more to do on this subject unless # +# you are using 'localhost'. # +# # +# 5. IMPORTANT: Only migrate to the new docker-compose # +# if you are using a recent version of the # +# application (at least v1.13.1). Otherwise, please # +# first run 'docker-compose.old.yaml' with updated # +# image versions before switching to the new one. # +# # +############################################################ + + + volumes: lago_postgres_data: lago_redis_data: