Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
8.3
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
404: Not Found
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Domain Default page</title>
|
||||||
|
<meta name="copyright" content="Copyright 1999-2025. WebPros International GmbH. All rights reserved.">
|
||||||
|
<script src="https://assets.plesk.com/static/default-website-content/public/default-website-index.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>What is Plesk</h2>
|
||||||
|
<p>
|
||||||
|
Plesk is a <a href="https://www.plesk.com">hosting panel</a> with simple and secure web server, website and web apps management tools. It is specially designed to help web professionals manage web, DNS, mail and other services through a comprehensive and user-friendly GUI. Plesk is about intelligently managing servers, apps, websites and hosting businesses, on both traditional and cloud hosting.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://docs.plesk.com/try-plesk-now/">Try Plesk Now!</a>
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://docs.plesk.com/en-US/obsidian/">Plesk Guides</a></li>
|
||||||
|
<li><a href="https://support.plesk.com/hc/en-us">Knowledge Base</a></li>
|
||||||
|
<li><a href="https://talk.plesk.com/">Forum</a></li>
|
||||||
|
<li><a href="https://www.plesk.com/blog/">Blog</a></li>
|
||||||
|
<li><a href="https://www.youtube.com/channel/UCeU-_6YHGQFcVSHLbEXLNlA/playlists">Video Guides</a></li>
|
||||||
|
<li><a href="https://www.facebook.com/Plesk">Facebook</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>Do you host WordPress sites outside of Plesk? Try <a href="https://wpguardian.io/">WP Guardian</a> - it provides complete visibility into the health of your WordPress websites in one place and keeps them protected with flexible updates management</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
x-db-env: &db-env
|
||||||
|
PGHOST: ${PGHOST:-plane-db}
|
||||||
|
PGDATABASE: ${PGDATABASE:-plane}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-plane}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-plane}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-plane}
|
||||||
|
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
|
||||||
|
PGDATA: ${PGDATA:-/var/lib/postgresql/data}
|
||||||
|
|
||||||
|
x-redis-env: &redis-env
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-plane-redis}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
REDIS_URL: ${REDIS_URL:-redis://plane-redis:6379/}
|
||||||
|
|
||||||
|
x-minio-env: &minio-env
|
||||||
|
MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
|
||||||
|
x-aws-s3-env: &aws-s3-env
|
||||||
|
AWS_REGION: ${AWS_REGION:-}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
|
||||||
|
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
|
||||||
|
x-proxy-env: &proxy-env
|
||||||
|
APP_DOMAIN: ${APP_DOMAIN:-localhost}
|
||||||
|
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||||||
|
CERT_EMAIL: ${CERT_EMAIL}
|
||||||
|
CERT_ACME_CA: ${CERT_ACME_CA}
|
||||||
|
CERT_ACME_DNS: ${CERT_ACME_DNS}
|
||||||
|
LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
|
||||||
|
LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
|
||||||
|
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
SITE_ADDRESS: ${SITE_ADDRESS:-:80}
|
||||||
|
|
||||||
|
x-mq-env: &mq-env # RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST: ${RABBITMQ_HOST:-plane-mq}
|
||||||
|
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
|
||||||
|
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-plane}
|
||||||
|
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-plane}
|
||||||
|
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
|
||||||
|
x-live-env: &live-env
|
||||||
|
API_BASE_URL: ${API_BASE_URL:-http://api:8000}
|
||||||
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
|
|
||||||
|
x-app-env: &app-env
|
||||||
|
WEB_URL: ${WEB_URL:-http://localhost}
|
||||||
|
DEBUG: ${DEBUG:-0}
|
||||||
|
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS}
|
||||||
|
GUNICORN_WORKERS: 1
|
||||||
|
USE_MINIO: ${USE_MINIO:-1}
|
||||||
|
DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
|
||||||
|
SECRET_KEY: ${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
|
||||||
|
AMQP_URL: ${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}
|
||||||
|
API_KEY_RATE_LIMIT: ${API_KEY_RATE_LIMIT:-60/minute}
|
||||||
|
MINIO_ENDPOINT_SSL: ${MINIO_ENDPOINT_SSL:-0}
|
||||||
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
|
WEBHOOK_ALLOWED_IPS: ${WEBHOOK_ALLOWED_IPS:-}
|
||||||
|
WEBHOOK_ALLOWED_HOSTS: ${WEBHOOK_ALLOWED_HOSTS:-}
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: makeplane/plane-frontend:${APP_RELEASE:-stable}
|
||||||
|
deploy:
|
||||||
|
replicas: ${WEB_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- worker
|
||||||
|
|
||||||
|
space:
|
||||||
|
image: makeplane/plane-space:${APP_RELEASE:-stable}
|
||||||
|
deploy:
|
||||||
|
replicas: ${SPACE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- worker
|
||||||
|
- web
|
||||||
|
|
||||||
|
admin:
|
||||||
|
image: makeplane/plane-admin:${APP_RELEASE:-stable}
|
||||||
|
deploy:
|
||||||
|
replicas: ${ADMIN_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
live:
|
||||||
|
image: makeplane/plane-live:${APP_RELEASE:-stable}
|
||||||
|
environment:
|
||||||
|
<<: [*live-env, *redis-env]
|
||||||
|
deploy:
|
||||||
|
replicas: ${LIVE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
api:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||||||
|
command: ./bin/docker-entrypoint-api.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${API_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_api:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
worker:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||||||
|
command: ./bin/docker-entrypoint-worker.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
beat-worker:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||||||
|
command: ./bin/docker-entrypoint-beat.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${BEAT_WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_beat-worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
migrator:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||||||
|
command: ./bin/docker-entrypoint-migrator.sh
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
volumes:
|
||||||
|
- logs_migrator:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
|
||||||
|
# Comment this if you already have a database running
|
||||||
|
plane-db:
|
||||||
|
image: postgres:15.7-alpine
|
||||||
|
command: postgres -c 'max_connections=1000'
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *db-env
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
plane-redis:
|
||||||
|
image: valkey/valkey:7.2.11-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- redisdata:/data
|
||||||
|
|
||||||
|
plane-mq:
|
||||||
|
image: rabbitmq:3.13.6-management-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *mq-env
|
||||||
|
volumes:
|
||||||
|
- rabbitmq_data:/var/lib/rabbitmq
|
||||||
|
|
||||||
|
# Comment this if you using any external s3 compatible storage
|
||||||
|
plane-minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
command: server /export --console-address ":9090"
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *minio-env
|
||||||
|
volumes:
|
||||||
|
- uploads:/export
|
||||||
|
|
||||||
|
# Comment this if you already have a reverse proxy running
|
||||||
|
proxy:
|
||||||
|
image: makeplane/plane-proxy:${APP_RELEASE:-stable}
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *proxy-env
|
||||||
|
ports:
|
||||||
|
- target: 80
|
||||||
|
published: ${LISTEN_HTTP_PORT:-80}
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 443
|
||||||
|
published: ${LISTEN_HTTPS_PORT:-443}
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
volumes:
|
||||||
|
- proxy_config:/config
|
||||||
|
- proxy_data:/data
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
- api
|
||||||
|
- space
|
||||||
|
- admin
|
||||||
|
- live
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
redisdata:
|
||||||
|
uploads:
|
||||||
|
logs_api:
|
||||||
|
logs_worker:
|
||||||
|
logs_beat-worker:
|
||||||
|
logs_migrator:
|
||||||
|
rabbitmq_data:
|
||||||
|
proxy_config:
|
||||||
|
proxy_data:
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
APP_DOMAIN=localhost
|
||||||
|
APP_RELEASE=stable
|
||||||
|
|
||||||
|
WEB_REPLICAS=1
|
||||||
|
SPACE_REPLICAS=1
|
||||||
|
ADMIN_REPLICAS=1
|
||||||
|
API_REPLICAS=1
|
||||||
|
WORKER_REPLICAS=1
|
||||||
|
BEAT_WORKER_REPLICAS=1
|
||||||
|
LIVE_REPLICAS=1
|
||||||
|
|
||||||
|
LISTEN_HTTP_PORT=80
|
||||||
|
LISTEN_HTTPS_PORT=443
|
||||||
|
|
||||||
|
WEB_URL=http://${APP_DOMAIN}
|
||||||
|
DEBUG=0
|
||||||
|
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
|
||||||
|
API_BASE_URL=http://api:8000
|
||||||
|
|
||||||
|
#DB SETTINGS
|
||||||
|
PGHOST=plane-db
|
||||||
|
PGDATABASE=plane
|
||||||
|
POSTGRES_USER=plane
|
||||||
|
POSTGRES_PASSWORD=plane
|
||||||
|
POSTGRES_DB=plane
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
PGDATA=/var/lib/postgresql/data
|
||||||
|
DATABASE_URL=
|
||||||
|
|
||||||
|
# REDIS SETTINGS
|
||||||
|
REDIS_HOST=plane-redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_URL=
|
||||||
|
|
||||||
|
# RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST=plane-mq
|
||||||
|
RABBITMQ_PORT=5672
|
||||||
|
RABBITMQ_USER=plane
|
||||||
|
RABBITMQ_PASSWORD=plane
|
||||||
|
RABBITMQ_VHOST=plane
|
||||||
|
AMQP_URL=
|
||||||
|
|
||||||
|
# If SSL Cert to be generated, set CERT_EMAIl="email <EMAIL_ADDRESS>"
|
||||||
|
CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
TRUSTED_PROXIES=0.0.0.0/0
|
||||||
|
SITE_ADDRESS=:80
|
||||||
|
CERT_EMAIL=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# For DNS Challenge based certificate generation, set the CERT_ACME_DNS, CERT_EMAIL
|
||||||
|
# CERT_ACME_DNS="acme_dns <CERT_DNS_PROVIDER> <CERT_DNS_PROVIDER_API_KEY>"
|
||||||
|
CERT_ACME_DNS=
|
||||||
|
|
||||||
|
|
||||||
|
# Secret Key
|
||||||
|
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
||||||
|
|
||||||
|
# DATA STORE SETTINGS
|
||||||
|
USE_MINIO=1
|
||||||
|
AWS_REGION=
|
||||||
|
AWS_ACCESS_KEY_ID=access-key
|
||||||
|
AWS_SECRET_ACCESS_KEY=secret-key
|
||||||
|
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
|
||||||
|
AWS_S3_BUCKET_NAME=uploads
|
||||||
|
FILE_SIZE_LIMIT=5242880
|
||||||
|
|
||||||
|
# Gunicorn Workers
|
||||||
|
GUNICORN_WORKERS=1
|
||||||
|
|
||||||
|
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
|
||||||
|
# DOCKER_PLATFORM=linux/amd64
|
||||||
|
|
||||||
|
# Force HTTPS for handling SSL Termination
|
||||||
|
MINIO_ENDPOINT_SSL=0
|
||||||
|
|
||||||
|
# API key rate limit
|
||||||
|
API_KEY_RATE_LIMIT=60/minute
|
||||||
|
|
||||||
|
# Live server environment variables
|
||||||
|
# WARNING: You must set a secure value for LIVE_SERVER_SECRET_KEY in production environments.
|
||||||
|
LIVE_SERVER_SECRET_KEY=
|
||||||
|
|
||||||
|
# Webhook IP allowlist — comma-separated IPs or CIDR ranges allowed as webhook targets
|
||||||
|
# even if they resolve to private networks (e.g. "10.0.0.0/8,192.168.1.0/24,172.16.0.5")
|
||||||
|
WEBHOOK_ALLOWED_IPS=
|
||||||
|
|
||||||
|
# Webhook hostname allowlist — comma-separated hostnames that bypass the private-IP
|
||||||
|
# SSRF check. Useful for trusted internal services whose container/service IPs are
|
||||||
|
# dynamic (e.g. "silo,silo.namespace.svc.cluster.local")
|
||||||
|
WEBHOOK_ALLOWED_HOSTS=
|
||||||
|
DOCKERHUB_USER=makeplane
|
||||||
|
PULL_POLICY=if_not_present
|
||||||
|
CUSTOM_BUILD=false
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
x-db-env: &db-env
|
||||||
|
PGHOST: ${PGHOST:-plane-db}
|
||||||
|
PGDATABASE: ${PGDATABASE:-plane}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-plane}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-plane}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-plane}
|
||||||
|
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
|
||||||
|
PGDATA: ${PGDATA:-/var/lib/postgresql/data}
|
||||||
|
|
||||||
|
x-redis-env: &redis-env
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-plane-redis}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
REDIS_URL: ${REDIS_URL:-redis://plane-redis:6379/}
|
||||||
|
|
||||||
|
x-minio-env: &minio-env
|
||||||
|
MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
|
||||||
|
x-aws-s3-env: &aws-s3-env
|
||||||
|
AWS_REGION: ${AWS_REGION:-}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
|
||||||
|
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
|
||||||
|
x-proxy-env: &proxy-env
|
||||||
|
APP_DOMAIN: ${APP_DOMAIN:-localhost}
|
||||||
|
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||||||
|
CERT_EMAIL: ${CERT_EMAIL}
|
||||||
|
CERT_ACME_CA: ${CERT_ACME_CA}
|
||||||
|
CERT_ACME_DNS: ${CERT_ACME_DNS}
|
||||||
|
LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
|
||||||
|
LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
|
||||||
|
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
SITE_ADDRESS: ${SITE_ADDRESS:-:80}
|
||||||
|
|
||||||
|
x-mq-env: &mq-env # RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST: ${RABBITMQ_HOST:-plane-mq}
|
||||||
|
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
|
||||||
|
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-plane}
|
||||||
|
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-plane}
|
||||||
|
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
|
||||||
|
x-live-env: &live-env
|
||||||
|
API_BASE_URL: ${API_BASE_URL:-http://api:8000}
|
||||||
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
|
|
||||||
|
x-app-env: &app-env
|
||||||
|
WEB_URL: ${WEB_URL:-http://localhost}
|
||||||
|
DEBUG: ${DEBUG:-0}
|
||||||
|
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS}
|
||||||
|
GUNICORN_WORKERS: 1
|
||||||
|
USE_MINIO: ${USE_MINIO:-1}
|
||||||
|
DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
|
||||||
|
SECRET_KEY: ${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
|
||||||
|
AMQP_URL: ${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}
|
||||||
|
API_KEY_RATE_LIMIT: ${API_KEY_RATE_LIMIT:-60/minute}
|
||||||
|
MINIO_ENDPOINT_SSL: ${MINIO_ENDPOINT_SSL:-0}
|
||||||
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
|
WEBHOOK_ALLOWED_IPS: ${WEBHOOK_ALLOWED_IPS:-}
|
||||||
|
WEBHOOK_ALLOWED_HOSTS: ${WEBHOOK_ALLOWED_HOSTS:-}
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: makeplane/plane-frontend:${APP_RELEASE:-v1.3.1}
|
||||||
|
deploy:
|
||||||
|
replicas: ${WEB_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- worker
|
||||||
|
|
||||||
|
space:
|
||||||
|
image: makeplane/plane-space:${APP_RELEASE:-v1.3.1}
|
||||||
|
deploy:
|
||||||
|
replicas: ${SPACE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- worker
|
||||||
|
- web
|
||||||
|
|
||||||
|
admin:
|
||||||
|
image: makeplane/plane-admin:${APP_RELEASE:-v1.3.1}
|
||||||
|
deploy:
|
||||||
|
replicas: ${ADMIN_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
live:
|
||||||
|
image: makeplane/plane-live:${APP_RELEASE:-v1.3.1}
|
||||||
|
environment:
|
||||||
|
<<: [*live-env, *redis-env]
|
||||||
|
deploy:
|
||||||
|
replicas: ${LIVE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
api:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.1}
|
||||||
|
command: ./bin/docker-entrypoint-api.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${API_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_api:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
worker:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.1}
|
||||||
|
command: ./bin/docker-entrypoint-worker.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
beat-worker:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.1}
|
||||||
|
command: ./bin/docker-entrypoint-beat.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${BEAT_WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- logs_beat-worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
|
migrator:
|
||||||
|
image: makeplane/plane-backend:${APP_RELEASE:-v1.3.1}
|
||||||
|
command: ./bin/docker-entrypoint-migrator.sh
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
volumes:
|
||||||
|
- logs_migrator:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [*app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env]
|
||||||
|
depends_on:
|
||||||
|
- plane-db
|
||||||
|
- plane-redis
|
||||||
|
|
||||||
|
# Comment this if you already have a database running
|
||||||
|
plane-db:
|
||||||
|
image: postgres:15.7-alpine
|
||||||
|
command: postgres -c 'max_connections=1000'
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *db-env
|
||||||
|
volumes:
|
||||||
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
plane-redis:
|
||||||
|
image: valkey/valkey:7.2.11-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
volumes:
|
||||||
|
- redisdata:/data
|
||||||
|
|
||||||
|
plane-mq:
|
||||||
|
image: rabbitmq:3.13.6-management-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *mq-env
|
||||||
|
volumes:
|
||||||
|
- rabbitmq_data:/var/lib/rabbitmq
|
||||||
|
|
||||||
|
# Comment this if you using any external s3 compatible storage
|
||||||
|
plane-minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
command: server /export --console-address ":9090"
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *minio-env
|
||||||
|
volumes:
|
||||||
|
- uploads:/export
|
||||||
|
|
||||||
|
# Comment this if you already have a reverse proxy running
|
||||||
|
proxy:
|
||||||
|
image: makeplane/plane-proxy:${APP_RELEASE:-v1.3.1}
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *proxy-env
|
||||||
|
ports:
|
||||||
|
- target: 80
|
||||||
|
published: ${LISTEN_HTTP_PORT:-80}
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 443
|
||||||
|
published: ${LISTEN_HTTPS_PORT:-443}
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
volumes:
|
||||||
|
- proxy_config:/config
|
||||||
|
- proxy_data:/data
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
- api
|
||||||
|
- space
|
||||||
|
- admin
|
||||||
|
- live
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pgdata:
|
||||||
|
redisdata:
|
||||||
|
uploads:
|
||||||
|
logs_api:
|
||||||
|
logs_worker:
|
||||||
|
logs_beat-worker:
|
||||||
|
logs_migrator:
|
||||||
|
rabbitmq_data:
|
||||||
|
proxy_config:
|
||||||
|
proxy_data:
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
APP_DOMAIN=plane.tesscorp.com.mx
|
||||||
|
APP_RELEASE=v1.3.1
|
||||||
|
|
||||||
|
WEB_REPLICAS=1
|
||||||
|
SPACE_REPLICAS=1
|
||||||
|
ADMIN_REPLICAS=1
|
||||||
|
API_REPLICAS=1
|
||||||
|
WORKER_REPLICAS=1
|
||||||
|
BEAT_WORKER_REPLICAS=1
|
||||||
|
LIVE_REPLICAS=1
|
||||||
|
|
||||||
|
LISTEN_HTTP_PORT=3040
|
||||||
|
LISTEN_HTTPS_PORT=3443
|
||||||
|
|
||||||
|
WEB_URL=https://${APP_DOMAIN}
|
||||||
|
DEBUG=0
|
||||||
|
CORS_ALLOWED_ORIGINS=https://${APP_DOMAIN}
|
||||||
|
API_BASE_URL=http://api:8000
|
||||||
|
|
||||||
|
#DB SETTINGS
|
||||||
|
PGHOST=plane-db
|
||||||
|
PGDATABASE=plane
|
||||||
|
POSTGRES_USER=plane
|
||||||
|
POSTGRES_PASSWORD=plane
|
||||||
|
POSTGRES_DB=plane
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
PGDATA=/var/lib/postgresql/data
|
||||||
|
DATABASE_URL=
|
||||||
|
|
||||||
|
# REDIS SETTINGS
|
||||||
|
REDIS_HOST=plane-redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_URL=
|
||||||
|
|
||||||
|
# RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST=plane-mq
|
||||||
|
RABBITMQ_PORT=5672
|
||||||
|
RABBITMQ_USER=plane
|
||||||
|
RABBITMQ_PASSWORD=plane
|
||||||
|
RABBITMQ_VHOST=plane
|
||||||
|
AMQP_URL=
|
||||||
|
|
||||||
|
# If SSL Cert to be generated, set CERT_EMAIl="email <EMAIL_ADDRESS>"
|
||||||
|
CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
TRUSTED_PROXIES=0.0.0.0/0
|
||||||
|
SITE_ADDRESS=:80
|
||||||
|
CERT_EMAIL=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# For DNS Challenge based certificate generation, set the CERT_ACME_DNS, CERT_EMAIL
|
||||||
|
# CERT_ACME_DNS="acme_dns <CERT_DNS_PROVIDER> <CERT_DNS_PROVIDER_API_KEY>"
|
||||||
|
CERT_ACME_DNS=
|
||||||
|
|
||||||
|
|
||||||
|
# Secret Key
|
||||||
|
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
||||||
|
|
||||||
|
# DATA STORE SETTINGS
|
||||||
|
USE_MINIO=1
|
||||||
|
AWS_REGION=
|
||||||
|
AWS_ACCESS_KEY_ID=access-key
|
||||||
|
AWS_SECRET_ACCESS_KEY=secret-key
|
||||||
|
AWS_S3_ENDPOINT_URL=https://plane.tesscorp.com.mx
|
||||||
|
AWS_S3_BUCKET_NAME=uploads
|
||||||
|
FILE_SIZE_LIMIT=5242880
|
||||||
|
|
||||||
|
# Gunicorn Workers
|
||||||
|
GUNICORN_WORKERS=1
|
||||||
|
|
||||||
|
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
|
||||||
|
# DOCKER_PLATFORM=linux/amd64
|
||||||
|
|
||||||
|
# Force HTTPS for handling SSL Termination
|
||||||
|
MINIO_ENDPOINT_SSL=1
|
||||||
|
|
||||||
|
# API key rate limit
|
||||||
|
API_KEY_RATE_LIMIT=60/minute
|
||||||
|
|
||||||
|
# Live server environment variables
|
||||||
|
# WARNING: You must set a secure value for LIVE_SERVER_SECRET_KEY in production environments.
|
||||||
|
LIVE_SERVER_SECRET_KEY=
|
||||||
|
|
||||||
|
# Webhook IP allowlist — comma-separated IPs or CIDR ranges allowed as webhook targets
|
||||||
|
# even if they resolve to private networks (e.g. "10.0.0.0/8,192.168.1.0/24,172.16.0.5")
|
||||||
|
WEBHOOK_ALLOWED_IPS=
|
||||||
|
|
||||||
|
# Webhook hostname allowlist — comma-separated hostnames that bypass the private-IP
|
||||||
|
# SSRF check. Useful for trusted internal services whose container/service IPs are
|
||||||
|
# dynamic (e.g. "silo,silo.namespace.svc.cluster.local")
|
||||||
|
WEBHOOK_ALLOWED_HOSTS=
|
||||||
|
DOCKERHUB_USER=makeplane
|
||||||
|
PULL_POLICY=if_not_present
|
||||||
|
CUSTOM_BUILD=false
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
APP_DOMAIN=localhost
|
||||||
|
APP_RELEASE=stable
|
||||||
|
|
||||||
|
WEB_REPLICAS=1
|
||||||
|
SPACE_REPLICAS=1
|
||||||
|
ADMIN_REPLICAS=1
|
||||||
|
API_REPLICAS=1
|
||||||
|
WORKER_REPLICAS=1
|
||||||
|
BEAT_WORKER_REPLICAS=1
|
||||||
|
LIVE_REPLICAS=1
|
||||||
|
|
||||||
|
LISTEN_HTTP_PORT=80
|
||||||
|
LISTEN_HTTPS_PORT=443
|
||||||
|
|
||||||
|
WEB_URL=http://${APP_DOMAIN}
|
||||||
|
DEBUG=0
|
||||||
|
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
|
||||||
|
API_BASE_URL=http://api:8000
|
||||||
|
|
||||||
|
#DB SETTINGS
|
||||||
|
PGHOST=plane-db
|
||||||
|
PGDATABASE=plane
|
||||||
|
POSTGRES_USER=plane
|
||||||
|
POSTGRES_PASSWORD=plane
|
||||||
|
POSTGRES_DB=plane
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
PGDATA=/var/lib/postgresql/data
|
||||||
|
DATABASE_URL=
|
||||||
|
|
||||||
|
# REDIS SETTINGS
|
||||||
|
REDIS_HOST=plane-redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_URL=
|
||||||
|
|
||||||
|
# RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST=plane-mq
|
||||||
|
RABBITMQ_PORT=5672
|
||||||
|
RABBITMQ_USER=plane
|
||||||
|
RABBITMQ_PASSWORD=plane
|
||||||
|
RABBITMQ_VHOST=plane
|
||||||
|
AMQP_URL=
|
||||||
|
|
||||||
|
# If SSL Cert to be generated, set CERT_EMAIl="email <EMAIL_ADDRESS>"
|
||||||
|
CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
TRUSTED_PROXIES=0.0.0.0/0
|
||||||
|
SITE_ADDRESS=:80
|
||||||
|
CERT_EMAIL=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# For DNS Challenge based certificate generation, set the CERT_ACME_DNS, CERT_EMAIL
|
||||||
|
# CERT_ACME_DNS="acme_dns <CERT_DNS_PROVIDER> <CERT_DNS_PROVIDER_API_KEY>"
|
||||||
|
CERT_ACME_DNS=
|
||||||
|
|
||||||
|
|
||||||
|
# Secret Key
|
||||||
|
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
||||||
|
|
||||||
|
# DATA STORE SETTINGS
|
||||||
|
USE_MINIO=1
|
||||||
|
AWS_REGION=
|
||||||
|
AWS_ACCESS_KEY_ID=access-key
|
||||||
|
AWS_SECRET_ACCESS_KEY=secret-key
|
||||||
|
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
|
||||||
|
AWS_S3_BUCKET_NAME=uploads
|
||||||
|
FILE_SIZE_LIMIT=5242880
|
||||||
|
|
||||||
|
# Gunicorn Workers
|
||||||
|
GUNICORN_WORKERS=1
|
||||||
|
|
||||||
|
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
|
||||||
|
# DOCKER_PLATFORM=linux/amd64
|
||||||
|
|
||||||
|
# Force HTTPS for handling SSL Termination
|
||||||
|
MINIO_ENDPOINT_SSL=0
|
||||||
|
|
||||||
|
# API key rate limit
|
||||||
|
API_KEY_RATE_LIMIT=60/minute
|
||||||
|
|
||||||
|
# Live server environment variables
|
||||||
|
# WARNING: You must set a secure value for LIVE_SERVER_SECRET_KEY in production environments.
|
||||||
|
LIVE_SERVER_SECRET_KEY=
|
||||||
|
|
||||||
|
# Webhook IP allowlist — comma-separated IPs or CIDR ranges allowed as webhook targets
|
||||||
|
# even if they resolve to private networks (e.g. "10.0.0.0/8,192.168.1.0/24,172.16.0.5")
|
||||||
|
WEBHOOK_ALLOWED_IPS=
|
||||||
|
|
||||||
|
# Webhook hostname allowlist — comma-separated hostnames that bypass the private-IP
|
||||||
|
# SSRF check. Useful for trusted internal services whose container/service IPs are
|
||||||
|
# dynamic (e.g. "silo,silo.namespace.svc.cluster.local")
|
||||||
|
WEBHOOK_ALLOWED_HOSTS=
|
||||||
|
DOCKERHUB_USER=makeplane
|
||||||
|
PULL_POLICY=if_not_present
|
||||||
|
CUSTOM_BUILD=false
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Plane Project Setup Script
|
||||||
|
# This script prepares the local development environment by setting up all necessary .env files
|
||||||
|
# https://github.com/makeplane/plane
|
||||||
|
|
||||||
|
# Set colors for output messages
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Print header
|
||||||
|
echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE} Plane - Project Management Tool ${NC}"
|
||||||
|
echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo -e "${BOLD}Setting up your development environment...${NC}\n"
|
||||||
|
|
||||||
|
# Function to handle file copying with error checking
|
||||||
|
copy_env_file() {
|
||||||
|
local source=$1
|
||||||
|
local destination=$2
|
||||||
|
|
||||||
|
if [ ! -f "$source" ]; then
|
||||||
|
echo -e "${RED}Error: Source file $source does not exist.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp "$source" "$destination"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} Copied $destination"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} Failed to copy $destination"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Export character encoding settings for macOS compatibility
|
||||||
|
export LC_ALL=C
|
||||||
|
export LC_CTYPE=C
|
||||||
|
echo -e "${YELLOW}Setting up environment files...${NC}"
|
||||||
|
|
||||||
|
# Copy all environment example files
|
||||||
|
services=("" "web" "api" "space" "admin" "live")
|
||||||
|
success=true
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
if [ "$service" == "" ]; then
|
||||||
|
# Handle root .env file
|
||||||
|
prefix="./"
|
||||||
|
else
|
||||||
|
# Handle service .env files in apps folder
|
||||||
|
prefix="./apps/$service/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
copy_env_file "${prefix}.env.example" "${prefix}.env" || success=false
|
||||||
|
done
|
||||||
|
|
||||||
|
# Generate SECRET_KEY for Django
|
||||||
|
if [ -f "./apps/api/.env" ]; then
|
||||||
|
echo -e "\n${YELLOW}Generating Django SECRET_KEY...${NC}"
|
||||||
|
SECRET_KEY=$(tr -dc 'a-z0-9' < /dev/urandom | head -c50)
|
||||||
|
|
||||||
|
if [ -z "$SECRET_KEY" ]; then
|
||||||
|
echo -e "${RED}Error: Failed to generate SECRET_KEY.${NC}"
|
||||||
|
echo -e "${RED}Ensure 'tr' and 'head' commands are available on your system.${NC}"
|
||||||
|
success=false
|
||||||
|
else
|
||||||
|
echo -e "SECRET_KEY=\"$SECRET_KEY\"" >> ./apps/api/.env
|
||||||
|
echo -e "${GREEN}✓${NC} Added SECRET_KEY to apps/api/.env"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} apps/api/.env not found. SECRET_KEY not added."
|
||||||
|
success=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Activate pnpm (version set in package.json)
|
||||||
|
corepack enable pnpm || success=false
|
||||||
|
# Install Node dependencies
|
||||||
|
pnpm install || success=false
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo -e "\n${YELLOW}Setup status:${NC}"
|
||||||
|
if [ "$success" = true ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} Environment setup completed successfully!\n"
|
||||||
|
echo -e "${BOLD}Next steps:${NC}"
|
||||||
|
echo -e "1. Review the .env files in each folder if needed"
|
||||||
|
echo -e "2. Start the services with: ${BOLD}docker compose -f docker-compose-local.yml up -d${NC}"
|
||||||
|
echo -e "\n${GREEN}Happy coding! 🚀${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} Some issues occurred during setup. Please check the errors above.\n"
|
||||||
|
echo -e "For help, visit: ${BLUE}https://github.com/makeplane/plane${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,714 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BRANCH=${BRANCH:-master}
|
||||||
|
SCRIPT_DIR=$PWD
|
||||||
|
SERVICE_FOLDER=plane-app
|
||||||
|
PLANE_INSTALL_DIR=$PWD/$SERVICE_FOLDER
|
||||||
|
export APP_RELEASE=stable
|
||||||
|
export DOCKERHUB_USER=makeplane
|
||||||
|
export PULL_POLICY=${PULL_POLICY:-if_not_present}
|
||||||
|
export GH_REPO=makeplane/plane
|
||||||
|
export RELEASE_DOWNLOAD_URL="https://github.com/$GH_REPO/releases/download"
|
||||||
|
export FALLBACK_DOWNLOAD_URL="https://raw.githubusercontent.com/$GH_REPO/$BRANCH/deployments/cli/community"
|
||||||
|
|
||||||
|
CPU_ARCH=$(uname -m)
|
||||||
|
OS_NAME=$(uname)
|
||||||
|
UPPER_CPU_ARCH=$(tr '[:lower:]' '[:upper:]' <<< "$CPU_ARCH")
|
||||||
|
|
||||||
|
mkdir -p $PLANE_INSTALL_DIR/archive
|
||||||
|
DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/plane.env
|
||||||
|
|
||||||
|
function print_header() {
|
||||||
|
clear
|
||||||
|
|
||||||
|
cat <<"EOF"
|
||||||
|
##+. ##+ .##-
|
||||||
|
######+.######-.######.
|
||||||
|
#######. -### +#####+.
|
||||||
|
#######. + +######.
|
||||||
|
#######. .#######
|
||||||
|
#######. .#######
|
||||||
|
####### + .#######
|
||||||
|
.+#####+ ###- .#######
|
||||||
|
.######.-#####+.+######
|
||||||
|
-##. -## .+##
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function spinner() {
|
||||||
|
local pid=$1
|
||||||
|
local delay=.5
|
||||||
|
local spinstr='|/-\'
|
||||||
|
|
||||||
|
if ! ps -p "$pid" > /dev/null; then
|
||||||
|
echo "Invalid PID: $pid"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
while ps -p "$pid" > /dev/null; do
|
||||||
|
local temp=${spinstr#?}
|
||||||
|
printf " [%c] " "$spinstr" >&2
|
||||||
|
local spinstr=$temp${spinstr%"$temp"}
|
||||||
|
sleep $delay
|
||||||
|
printf "\b\b\b\b\b\b" >&2
|
||||||
|
done
|
||||||
|
printf " \b\b\b\b" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkLatestRelease(){
|
||||||
|
echo "Checking for the latest release..." >&2
|
||||||
|
local latest_release="v1.3.1"
|
||||||
|
if [ -z "$latest_release" ]; then
|
||||||
|
echo "Failed to check for the latest release. Exiting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $latest_release
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize(){
|
||||||
|
printf "Please wait while we check the availability of Docker images for the selected release ($APP_RELEASE) with ${UPPER_CPU_ARCH} support." >&2
|
||||||
|
|
||||||
|
if [ "$CUSTOM_BUILD" == "true" ]; then
|
||||||
|
echo "" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "${UPPER_CPU_ARCH} images are not available for selected release ($APP_RELEASE)." >&2
|
||||||
|
echo "build"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local IMAGE_NAME=makeplane/plane-proxy
|
||||||
|
local IMAGE_TAG=${APP_RELEASE}
|
||||||
|
docker manifest inspect "${IMAGE_NAME}:${IMAGE_TAG}" | grep -q "\"architecture\": \"${CPU_ARCH}\"" &
|
||||||
|
local pid=$!
|
||||||
|
spinner "$pid"
|
||||||
|
|
||||||
|
echo "" >&2
|
||||||
|
|
||||||
|
wait "$pid"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Plane supports ${CPU_ARCH}" >&2
|
||||||
|
echo "available"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "" >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "${UPPER_CPU_ARCH} images are not available for selected release ($APP_RELEASE)." >&2
|
||||||
|
echo "" >&2
|
||||||
|
echo "build"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function getEnvValue() {
|
||||||
|
local key=$1
|
||||||
|
local file=$2
|
||||||
|
|
||||||
|
if [ -z "$key" ] || [ -z "$file" ]; then
|
||||||
|
echo "Invalid arguments supplied"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
grep -q "^$key=" "$file"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
local value
|
||||||
|
value=$(grep "^$key=" "$file" | cut -d'=' -f2)
|
||||||
|
echo "$value"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function updateEnvFile() {
|
||||||
|
local key=$1
|
||||||
|
local value=$2
|
||||||
|
local file=$3
|
||||||
|
|
||||||
|
if [ -z "$key" ] || [ -z "$value" ] || [ -z "$file" ]; then
|
||||||
|
echo "Invalid arguments supplied"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
# check if key exists in the file
|
||||||
|
grep -q "^$key=" "$file"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "$key=$value" >> "$file"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
if [ "$OS_NAME" == "Darwin" ]; then
|
||||||
|
value=$(echo "$value" | sed 's/|/\\|/g')
|
||||||
|
sed -i '' "s|^$key=.*|$key=$value|g" "$file"
|
||||||
|
else
|
||||||
|
value=$(echo "$value" | sed 's/\//\\\//g')
|
||||||
|
sed -i "s/^$key=.*/$key=$value/g" "$file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "File not found: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCustomVariables(){
|
||||||
|
echo "Updating custom variables..." >&2
|
||||||
|
updateEnvFile "DOCKERHUB_USER" "$DOCKERHUB_USER" "$DOCKER_ENV_PATH"
|
||||||
|
updateEnvFile "APP_RELEASE" "$APP_RELEASE" "$DOCKER_ENV_PATH"
|
||||||
|
updateEnvFile "PULL_POLICY" "$PULL_POLICY" "$DOCKER_ENV_PATH"
|
||||||
|
updateEnvFile "CUSTOM_BUILD" "$CUSTOM_BUILD" "$DOCKER_ENV_PATH"
|
||||||
|
echo "Custom variables updated successfully" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncEnvFile(){
|
||||||
|
echo "Syncing environment variables..." >&2
|
||||||
|
if [ -f "$PLANE_INSTALL_DIR/plane.env.bak" ]; then
|
||||||
|
updateCustomVariables
|
||||||
|
|
||||||
|
# READ keys of plane.env and update the values from plane.env.bak
|
||||||
|
while IFS= read -r line
|
||||||
|
do
|
||||||
|
# ignore is the line is empty or starts with #
|
||||||
|
if [ -z "$line" ] || [[ $line == \#* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
key=$(echo "$line" | cut -d'=' -f1)
|
||||||
|
value=$(getEnvValue "$key" "$PLANE_INSTALL_DIR/plane.env.bak")
|
||||||
|
if [ -n "$value" ]; then
|
||||||
|
updateEnvFile "$key" "$value" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
done < "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
echo "Environment variables synced successfully" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildYourOwnImage(){
|
||||||
|
echo "Building images locally..."
|
||||||
|
|
||||||
|
export DOCKERHUB_USER="myplane"
|
||||||
|
export APP_RELEASE="local"
|
||||||
|
export PULL_POLICY="never"
|
||||||
|
CUSTOM_BUILD="true"
|
||||||
|
|
||||||
|
# checkout the code to ~/tmp/plane folder and build the images
|
||||||
|
local PLANE_TEMP_CODE_DIR=~/tmp/plane
|
||||||
|
rm -rf $PLANE_TEMP_CODE_DIR
|
||||||
|
mkdir -p $PLANE_TEMP_CODE_DIR
|
||||||
|
REPO=https://github.com/$GH_REPO.git
|
||||||
|
git clone "$REPO" "$PLANE_TEMP_CODE_DIR" --branch "$BRANCH" --single-branch --depth 1
|
||||||
|
|
||||||
|
cp "$PLANE_TEMP_CODE_DIR/deployments/cli/community/build.yml" "$PLANE_TEMP_CODE_DIR/build.yml"
|
||||||
|
|
||||||
|
cd "$PLANE_TEMP_CODE_DIR" || exit
|
||||||
|
|
||||||
|
/bin/bash -c "$COMPOSE_CMD -f build.yml build --no-cache" >&2
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Build failed. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Build completed successfully"
|
||||||
|
echo ""
|
||||||
|
echo "You can now start the services by running the command: ./setup.sh start"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function install() {
|
||||||
|
echo "Begin Installing Plane"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$APP_RELEASE" == "stable" ]; then
|
||||||
|
export APP_RELEASE=$(checkLatestRelease)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local build_image=$(initialize)
|
||||||
|
|
||||||
|
if [ "$build_image" == "build" ]; then
|
||||||
|
# ask for confirmation to continue building the images
|
||||||
|
echo "Do you want to continue with building the Docker images locally?"
|
||||||
|
read -p "Continue? [y/N]: " confirm
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Exiting..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$build_image" == "build" ]; then
|
||||||
|
download "true"
|
||||||
|
else
|
||||||
|
download "false"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function download() {
|
||||||
|
local LOCAL_BUILD=$1
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
TS=$(date +%s)
|
||||||
|
if [ -f "$PLANE_INSTALL_DIR/docker-compose.yaml" ]
|
||||||
|
then
|
||||||
|
mv $PLANE_INSTALL_DIR/docker-compose.yaml $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -sSL -H 'Cache-Control: no-cache, no-store' -w "HTTPSTATUS:%{http_code}" "$RELEASE_DOWNLOAD_URL/$APP_RELEASE/docker-compose.yml?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
else
|
||||||
|
# Fallback to download from the raw github url
|
||||||
|
RESPONSE=$(curl -sSL -H 'Cache-Control: no-cache, no-store' -w "HTTPSTATUS:%{http_code}" "$FALLBACK_DOWNLOAD_URL/docker-compose.yml?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
else
|
||||||
|
echo "Failed to download docker-compose.yml. HTTP Status: $STATUS"
|
||||||
|
echo "URL: $RELEASE_DOWNLOAD_URL/$APP_RELEASE/docker-compose.yml"
|
||||||
|
mv $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -sSL -H 'Cache-Control: no-cache, no-store' -w "HTTPSTATUS:%{http_code}" "$RELEASE_DOWNLOAD_URL/$APP_RELEASE/variables.env?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/variables-upgrade.env
|
||||||
|
else
|
||||||
|
# Fallback to download from the raw github url
|
||||||
|
RESPONSE=$(curl -sSL -H 'Cache-Control: no-cache, no-store' -w "HTTPSTATUS:%{http_code}" "$FALLBACK_DOWNLOAD_URL/variables.env?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/variables-upgrade.env
|
||||||
|
else
|
||||||
|
echo "Failed to download variables.env. HTTP Status: $STATUS"
|
||||||
|
echo "URL: $RELEASE_DOWNLOAD_URL/$APP_RELEASE/variables.env"
|
||||||
|
mv $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ];
|
||||||
|
then
|
||||||
|
cp "$DOCKER_ENV_PATH" "$PLANE_INSTALL_DIR/archive/$TS.env"
|
||||||
|
cp "$DOCKER_ENV_PATH" "$PLANE_INSTALL_DIR/plane.env.bak"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv $PLANE_INSTALL_DIR/variables-upgrade.env $DOCKER_ENV_PATH
|
||||||
|
|
||||||
|
syncEnvFile
|
||||||
|
|
||||||
|
if [ "$LOCAL_BUILD" == "true" ]; then
|
||||||
|
export DOCKERHUB_USER="myplane"
|
||||||
|
export APP_RELEASE="local"
|
||||||
|
export PULL_POLICY="never"
|
||||||
|
CUSTOM_BUILD="true"
|
||||||
|
|
||||||
|
buildYourOwnImage
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Build failed. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
updateCustomVariables
|
||||||
|
else
|
||||||
|
CUSTOM_BUILD="false"
|
||||||
|
updateCustomVariables
|
||||||
|
/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH pull --policy always"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Failed to pull the images. Exiting..."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Most recent version of Plane is now available for you to use"
|
||||||
|
echo ""
|
||||||
|
echo "In case of 'Upgrade', please check the 'plane.env 'file for any new variables and update them accordingly"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
function startServices() {
|
||||||
|
/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH up -d --pull if_not_present --quiet-pull"
|
||||||
|
|
||||||
|
local migrator_container_id=$(docker container ls -aq -f "name=$SERVICE_FOLDER-migrator")
|
||||||
|
if [ -n "$migrator_container_id" ]; then
|
||||||
|
local idx=0
|
||||||
|
while docker inspect --format='{{.State.Status}}' $migrator_container_id | grep -q "running"; do
|
||||||
|
local message=">> Waiting for Data Migration to finish"
|
||||||
|
local dots=$(printf '%*s' $idx | tr ' ' '.')
|
||||||
|
echo -ne "\r$message$dots"
|
||||||
|
((idx++))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
printf "\r\033[K"
|
||||||
|
echo ""
|
||||||
|
echo " Data Migration completed successfully ✅"
|
||||||
|
|
||||||
|
# if migrator exit status is not 0, show error message and exit
|
||||||
|
if [ -n "$migrator_container_id" ]; then
|
||||||
|
local migrator_exit_code=$(docker inspect --format='{{.State.ExitCode}}' $migrator_container_id)
|
||||||
|
if [ $migrator_exit_code -ne 0 ]; then
|
||||||
|
echo "Plane Server failed to start ❌"
|
||||||
|
# stopServices
|
||||||
|
echo
|
||||||
|
echo "Please check the logs for the 'migrator' service and resolve the issue(s)."
|
||||||
|
echo "Stop the services by running the command: ./setup.sh stop"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local api_container_id=$(docker container ls -q -f "name=$SERVICE_FOLDER-api")
|
||||||
|
|
||||||
|
# Verify container exists
|
||||||
|
if [ -z "$api_container_id" ]; then
|
||||||
|
echo " Error: API container not found. Please check if services are running."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local idx2=0
|
||||||
|
local api_ready=true # assume success, flip on timeout
|
||||||
|
local max_wait_time=300 # 5 minutes timeout
|
||||||
|
local start_time=$(date +%s)
|
||||||
|
|
||||||
|
echo " Waiting for API Service to be ready..."
|
||||||
|
while ! docker exec "$api_container_id" python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/', timeout=3)" > /dev/null 2>&1; do
|
||||||
|
local current_time=$(date +%s)
|
||||||
|
local elapsed_time=$((current_time - start_time))
|
||||||
|
|
||||||
|
if [ $elapsed_time -gt $max_wait_time ]; then
|
||||||
|
echo ""
|
||||||
|
echo " API Service health check timed out after 5 minutes"
|
||||||
|
echo " Checking if API container is still running..."
|
||||||
|
if docker ps | grep -q "$SERVICE_FOLDER-api"; then
|
||||||
|
echo " API container is running but did not pass the health-check. Continuing without marking it ready."
|
||||||
|
api_ready=false
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo " API container is not running. Please check logs."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local message=">> Waiting for API Service to Start (${elapsed_time}s)"
|
||||||
|
local dots=$(printf '%*s' $idx2 | tr ' ' '.')
|
||||||
|
echo -ne "\r$message$dots"
|
||||||
|
((idx2++))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
printf "\r\033[K"
|
||||||
|
if [ "$api_ready" = true ]; then
|
||||||
|
echo " API Service started successfully ✅"
|
||||||
|
else
|
||||||
|
echo " ⚠️ API Service did not respond to health-check – please verify manually."
|
||||||
|
fi
|
||||||
|
source "${DOCKER_ENV_PATH}"
|
||||||
|
echo " Plane Server started successfully ✅"
|
||||||
|
echo ""
|
||||||
|
echo " You can access the application at $WEB_URL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
}
|
||||||
|
function stopServices() {
|
||||||
|
/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH --env-file=$DOCKER_ENV_PATH down"
|
||||||
|
}
|
||||||
|
function restartServices() {
|
||||||
|
stopServices
|
||||||
|
startServices
|
||||||
|
}
|
||||||
|
function upgrade() {
|
||||||
|
local latest_release=$(checkLatestRelease)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Current release: $APP_RELEASE"
|
||||||
|
|
||||||
|
if [ "$latest_release" == "$APP_RELEASE" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "You are already using the latest release"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Latest release: $latest_release"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for confirmation to upgrade
|
||||||
|
echo "Do you want to upgrade to the latest release ($latest_release)?"
|
||||||
|
read -p "Continue? [y/N]: " confirm
|
||||||
|
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Exiting..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
export APP_RELEASE=$latest_release
|
||||||
|
|
||||||
|
echo "Upgrading Plane to the latest release..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "***** STOPPING SERVICES ****"
|
||||||
|
stopServices
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "***** DOWNLOADING STABLE VERSION ****"
|
||||||
|
install
|
||||||
|
|
||||||
|
echo "***** PLEASE VALIDATE AND START SERVICES ****"
|
||||||
|
}
|
||||||
|
function viewSpecificLogs(){
|
||||||
|
local SERVICE_NAME=$1
|
||||||
|
|
||||||
|
if /bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH ps | grep -q '$SERVICE_NAME'"; then
|
||||||
|
echo "Service '$SERVICE_NAME' is running."
|
||||||
|
else
|
||||||
|
echo "Service '$SERVICE_NAME' is not running."
|
||||||
|
fi
|
||||||
|
|
||||||
|
/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH logs -f $SERVICE_NAME"
|
||||||
|
}
|
||||||
|
function viewLogs(){
|
||||||
|
|
||||||
|
ARG_SERVICE_NAME=$2
|
||||||
|
|
||||||
|
if [ -z "$ARG_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
echo
|
||||||
|
echo "Select a Service you want to view the logs for:"
|
||||||
|
echo " 1) Web"
|
||||||
|
echo " 2) Space"
|
||||||
|
echo " 3) API"
|
||||||
|
echo " 4) Worker"
|
||||||
|
echo " 5) Beat-Worker"
|
||||||
|
echo " 6) Migrator"
|
||||||
|
echo " 7) Proxy"
|
||||||
|
echo " 8) Redis"
|
||||||
|
echo " 9) Postgres"
|
||||||
|
echo " 10) Minio"
|
||||||
|
echo " 11) RabbitMQ"
|
||||||
|
echo " 0) Back to Main Menu"
|
||||||
|
echo
|
||||||
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
|
|
||||||
|
until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 11 )); do
|
||||||
|
echo "Invalid selection. Please enter a number between 0 and 11."
|
||||||
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$DOCKER_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
echo "INVALID SERVICE NAME SUPPLIED"
|
||||||
|
else
|
||||||
|
case $DOCKER_SERVICE_NAME in
|
||||||
|
1) viewSpecificLogs "web";;
|
||||||
|
2) viewSpecificLogs "space";;
|
||||||
|
3) viewSpecificLogs "api";;
|
||||||
|
4) viewSpecificLogs "worker";;
|
||||||
|
5) viewSpecificLogs "beat-worker";;
|
||||||
|
6) viewSpecificLogs "migrator";;
|
||||||
|
7) viewSpecificLogs "proxy";;
|
||||||
|
8) viewSpecificLogs "plane-redis";;
|
||||||
|
9) viewSpecificLogs "plane-db";;
|
||||||
|
10) viewSpecificLogs "plane-minio";;
|
||||||
|
11) viewSpecificLogs "plane-mq";;
|
||||||
|
0) askForAction;;
|
||||||
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
elif [ -n "$ARG_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
ARG_SERVICE_NAME=$(echo "$ARG_SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
case $ARG_SERVICE_NAME in
|
||||||
|
web) viewSpecificLogs "web";;
|
||||||
|
space) viewSpecificLogs "space";;
|
||||||
|
api) viewSpecificLogs "api";;
|
||||||
|
worker) viewSpecificLogs "worker";;
|
||||||
|
beat-worker) viewSpecificLogs "beat-worker";;
|
||||||
|
migrator) viewSpecificLogs "migrator";;
|
||||||
|
proxy) viewSpecificLogs "proxy";;
|
||||||
|
redis) viewSpecificLogs "plane-redis";;
|
||||||
|
postgres) viewSpecificLogs "plane-db";;
|
||||||
|
minio) viewSpecificLogs "plane-minio";;
|
||||||
|
rabbitmq) viewSpecificLogs "plane-mq";;
|
||||||
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "INVALID SERVICE NAME SUPPLIED"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function backup_container_dir() {
|
||||||
|
local BACKUP_FOLDER=$1
|
||||||
|
local CONTAINER_NAME=$2
|
||||||
|
local CONTAINER_DATA_DIR=$3
|
||||||
|
local SERVICE_FOLDER=$4
|
||||||
|
|
||||||
|
echo "Backing up $CONTAINER_NAME data..."
|
||||||
|
local CONTAINER_ID=$(/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH ps -q $CONTAINER_NAME")
|
||||||
|
if [ -z "$CONTAINER_ID" ]; then
|
||||||
|
echo "Error: $CONTAINER_NAME container not found. Make sure the services are running."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a temporary directory for the backup
|
||||||
|
mkdir -p "$BACKUP_FOLDER/$SERVICE_FOLDER"
|
||||||
|
|
||||||
|
# Copy the data directory from the running container
|
||||||
|
echo "Copying $CONTAINER_NAME data directory..."
|
||||||
|
docker cp -q "$CONTAINER_ID:$CONTAINER_DATA_DIR/." "$BACKUP_FOLDER/$SERVICE_FOLDER/"
|
||||||
|
local cp_status=$?
|
||||||
|
|
||||||
|
if [ $cp_status -ne 0 ]; then
|
||||||
|
echo "Error: Failed to copy $SERVICE_FOLDER data"
|
||||||
|
rm -rf $BACKUP_FOLDER/$SERVICE_FOLDER
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create tar.gz of the data
|
||||||
|
cd "$BACKUP_FOLDER"
|
||||||
|
tar -czf "${SERVICE_FOLDER}.tar.gz" "$SERVICE_FOLDER/"
|
||||||
|
local tar_status=$?
|
||||||
|
if [ $tar_status -eq 0 ]; then
|
||||||
|
rm -rf "$SERVICE_FOLDER/"
|
||||||
|
fi
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
if [ $tar_status -ne 0 ]; then
|
||||||
|
echo "Error: Failed to create tar archive"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Successfully backed up $SERVICE_FOLDER data"
|
||||||
|
}
|
||||||
|
|
||||||
|
function backupData() {
|
||||||
|
local datetime=$(date +"%Y%m%d-%H%M")
|
||||||
|
local BACKUP_FOLDER=$PLANE_INSTALL_DIR/backup/$datetime
|
||||||
|
mkdir -p "$BACKUP_FOLDER"
|
||||||
|
|
||||||
|
# Check if docker-compose.yml exists
|
||||||
|
if [ ! -f "$DOCKER_FILE_PATH" ]; then
|
||||||
|
echo "Error: docker-compose.yml not found at $DOCKER_FILE_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
backup_container_dir "$BACKUP_FOLDER" "plane-db" "/var/lib/postgresql/data" "pgdata" || exit 1
|
||||||
|
backup_container_dir "$BACKUP_FOLDER" "plane-minio" "/export" "uploads" || exit 1
|
||||||
|
backup_container_dir "$BACKUP_FOLDER" "plane-mq" "/var/lib/rabbitmq" "rabbitmq_data" || exit 1
|
||||||
|
backup_container_dir "$BACKUP_FOLDER" "plane-redis" "/data" "redisdata" || exit 1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Backup completed successfully. Backup files are stored in $BACKUP_FOLDER"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
function askForAction() {
|
||||||
|
local DEFAULT_ACTION=$1
|
||||||
|
|
||||||
|
if [ -z "$DEFAULT_ACTION" ];
|
||||||
|
then
|
||||||
|
echo
|
||||||
|
echo "Select a Action you want to perform:"
|
||||||
|
echo " 1) Install"
|
||||||
|
echo " 2) Start"
|
||||||
|
echo " 3) Stop"
|
||||||
|
echo " 4) Restart"
|
||||||
|
echo " 5) Upgrade"
|
||||||
|
echo " 6) View Logs"
|
||||||
|
echo " 7) Backup Data"
|
||||||
|
echo " 8) Exit"
|
||||||
|
echo
|
||||||
|
read -p "Action [2]: " ACTION
|
||||||
|
until [[ -z "$ACTION" || "$ACTION" =~ ^[1-8]$ ]]; do
|
||||||
|
echo "$ACTION: invalid selection."
|
||||||
|
read -p "Action [2]: " ACTION
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$ACTION" ];
|
||||||
|
then
|
||||||
|
ACTION=2
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ACTION" == "1" ] || [ "$DEFAULT_ACTION" == "install" ];
|
||||||
|
then
|
||||||
|
install
|
||||||
|
# askForAction
|
||||||
|
elif [ "$ACTION" == "2" ] || [ "$DEFAULT_ACTION" == "start" ];
|
||||||
|
then
|
||||||
|
startServices
|
||||||
|
# askForAction
|
||||||
|
elif [ "$ACTION" == "3" ] || [ "$DEFAULT_ACTION" == "stop" ];
|
||||||
|
then
|
||||||
|
stopServices
|
||||||
|
# askForAction
|
||||||
|
elif [ "$ACTION" == "4" ] || [ "$DEFAULT_ACTION" == "restart" ];
|
||||||
|
then
|
||||||
|
restartServices
|
||||||
|
# askForAction
|
||||||
|
elif [ "$ACTION" == "5" ] || [ "$DEFAULT_ACTION" == "upgrade" ];
|
||||||
|
then
|
||||||
|
upgrade
|
||||||
|
# askForAction
|
||||||
|
elif [ "$ACTION" == "6" ] || [ "$DEFAULT_ACTION" == "logs" ];
|
||||||
|
then
|
||||||
|
viewLogs "$@"
|
||||||
|
askForAction
|
||||||
|
elif [ "$ACTION" == "7" ] || [ "$DEFAULT_ACTION" == "backup" ];
|
||||||
|
then
|
||||||
|
backupData
|
||||||
|
elif [ "$ACTION" == "8" ]
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "INVALID ACTION SUPPLIED"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# if docker-compose is installed
|
||||||
|
if command -v docker-compose &> /dev/null
|
||||||
|
then
|
||||||
|
COMPOSE_CMD="docker-compose"
|
||||||
|
else
|
||||||
|
COMPOSE_CMD="docker compose"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CPU_ARCH" == "x86_64" ] || [ "$CPU_ARCH" == "amd64" ]; then
|
||||||
|
CPU_ARCH="amd64"
|
||||||
|
elif [ "$CPU_ARCH" == "aarch64" ] || [ "$CPU_ARCH" == "arm64" ]; then
|
||||||
|
CPU_ARCH="arm64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
DOCKERHUB_USER=$(getEnvValue "DOCKERHUB_USER" "$DOCKER_ENV_PATH")
|
||||||
|
APP_RELEASE=$(getEnvValue "APP_RELEASE" "$DOCKER_ENV_PATH")
|
||||||
|
PULL_POLICY=$(getEnvValue "PULL_POLICY" "$DOCKER_ENV_PATH")
|
||||||
|
CUSTOM_BUILD=$(getEnvValue "CUSTOM_BUILD" "$DOCKER_ENV_PATH")
|
||||||
|
|
||||||
|
if [ -z "$DOCKERHUB_USER" ]; then
|
||||||
|
DOCKERHUB_USER=makeplane
|
||||||
|
updateEnvFile "DOCKERHUB_USER" "$DOCKERHUB_USER" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$APP_RELEASE" ]; then
|
||||||
|
APP_RELEASE=stable
|
||||||
|
updateEnvFile "APP_RELEASE" "$APP_RELEASE" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PULL_POLICY" ]; then
|
||||||
|
PULL_POLICY=if_not_present
|
||||||
|
updateEnvFile "PULL_POLICY" "$PULL_POLICY" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CUSTOM_BUILD" ]; then
|
||||||
|
CUSTOM_BUILD=false
|
||||||
|
updateEnvFile "CUSTOM_BUILD" "$CUSTOM_BUILD" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_header
|
||||||
|
askForAction "$@"
|
||||||
Submodule
+1
Submodule src added at bed58d9b17
Reference in New Issue
Block a user