initial commit
This commit is contained in:
55
.env.example
Normal file
55
.env.example
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Penpot Environment Variables Template
|
||||||
|
# Copy this file to .env and fill in the secure values.
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# ENVIRONMENT TOGGLE: DEV vs PRODUCTION
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# ---> OPTION A: DEVELOPMENT (No SSL / Plain HTTP)
|
||||||
|
# Prefix your IP or localhost with http:// to disable SSL generation.
|
||||||
|
# CADDY_SITE_ADDRESS=http://192.168.1.50
|
||||||
|
# PENPOT_PUBLIC_URI=http://192.168.1.50
|
||||||
|
|
||||||
|
# ---> OPTION B: PRODUCTION (Automatic SSL via Let's Encrypt)
|
||||||
|
# Comment out Option A, and uncomment these two lines.
|
||||||
|
# Do NOT prefix CADDY_SITE_ADDRESS with https://, just the domain.
|
||||||
|
# CADDY_SITE_ADDRESS=design.yourdomain.com
|
||||||
|
# PENPOT_PUBLIC_URI=https://design.yourdomain.com
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# --- Domain and SSL Setup ---
|
||||||
|
CADDY_SITE_ADDRESS=https://design.yourdomain.com
|
||||||
|
PENPOT_PUBLIC_URI=https://design.yourdomain.com
|
||||||
|
TLS_EMAIL=admin@yourdomain.com
|
||||||
|
|
||||||
|
# --- Security ---
|
||||||
|
# Generate a random string for this (e.g., using `openssl rand -base64 32`)
|
||||||
|
PENPOT_SECRET_KEY=your_super_secret_key_here
|
||||||
|
|
||||||
|
# --- Database Setup ---
|
||||||
|
# Must match between PostgreSQL and Backend
|
||||||
|
POSTGRES_USER=penpot
|
||||||
|
POSTGRES_PASSWORD=your_secure_db_password
|
||||||
|
POSTGRES_DB=penpot
|
||||||
|
PENPOT_DATABASE_URI=postgresql://penpot-postgres/penpot
|
||||||
|
PENPOT_DATABASE_USERNAME=penpot
|
||||||
|
PENPOT_DATABASE_PASSWORD=your_secure_db_password
|
||||||
|
|
||||||
|
# --- Redis Setup ---
|
||||||
|
PENPOT_REDIS_URI=redis://penpot-redis/0
|
||||||
|
|
||||||
|
# --- Telemetry (Optional) ---
|
||||||
|
# Set to true to disable sending anonymous telemetry to Penpot
|
||||||
|
PENPOT_TELEMETRY_ENABLED=false
|
||||||
|
|
||||||
|
# --- Email (SMTP) Configuration ---
|
||||||
|
# Required for user registration, password resets, and team invites
|
||||||
|
PENPOT_SMTP_DEFAULT_FROM=penpot@yourdomain.com
|
||||||
|
PENPOT_SMTP_DEFAULT_REPLY_TO=penpot@yourdomain.com
|
||||||
|
PENPOT_SMTP_HOST=smtp.yourprovider.com
|
||||||
|
PENPOT_SMTP_PORT=587
|
||||||
|
PENPOT_SMTP_USERNAME=your_smtp_username
|
||||||
|
PENPOT_SMTP_PASSWORD=your_smtp_password
|
||||||
|
PENPOT_SMTP_TLS=true
|
||||||
|
PENPOT_SMTP_SSL=false
|
||||||
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Ignore environment variables containing secrets
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Ignore persistent data volumes
|
||||||
|
volumes/
|
||||||
|
*/volumes/
|
||||||
|
*data/
|
||||||
|
assets/
|
||||||
|
|
||||||
|
# Ignore backups
|
||||||
|
backups/
|
||||||
|
*.tar.gz
|
||||||
|
*.sql
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Self-Hosted Penpot Deployment
|
||||||
|
|
||||||
|
This repository contains the infrastructure configuration to run Penpot via Docker Compose.
|
||||||
|
|
||||||
|
## Deployment Instructions
|
||||||
|
|
||||||
|
1. **Clone the repository:**
|
||||||
|
git clone http://git.amiirkhl.ir/interanet/penpot-deployment.git
|
||||||
|
cd penpot-deployment
|
||||||
|
|
||||||
|
2. **Setup Environment Variables:**
|
||||||
|
cp .env.example .env
|
||||||
|
# Edit the .env file and add your secret keys, passwords, and SMTP details
|
||||||
|
nano .env
|
||||||
|
|
||||||
|
3. **Start the Services:**
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
4. **Create the First Admin User:**
|
||||||
|
Once the containers are running, you need to create your main admin account via the command line:
|
||||||
|
docker exec -it penpot-backend ./manage.sh create-profile
|
||||||
4
config/caddy/Caddyfile
Normal file
4
config/caddy/Caddyfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{$DOMAIN} {
|
||||||
|
tls {$TLS_EMAIL}
|
||||||
|
reverse_proxy penpot-frontend:80
|
||||||
|
}
|
||||||
77
docker-compose.yml
Normal file
77
docker-compose.yml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
penpot:
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
penpot_postgres_v15:
|
||||||
|
penpot_tenant_assets:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
|
||||||
|
services:
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./config/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
environment:
|
||||||
|
- CADDY_SITE_ADDRESS=${CADDY_SITE_ADDRESS}
|
||||||
|
- TLS_EMAIL=${TLS_EMAIL}
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
|
depends_on:
|
||||||
|
- penpot-frontend
|
||||||
|
|
||||||
|
penpot-frontend:
|
||||||
|
image: "penpotapp/frontend:latest"
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- penpot_tenant_assets:/opt/data/assets
|
||||||
|
depends_on:
|
||||||
|
- penpot-backend
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
|
|
||||||
|
penpot-backend:
|
||||||
|
image: "penpotapp/backend:latest"
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- penpot_tenant_assets:/opt/data/assets
|
||||||
|
depends_on:
|
||||||
|
- penpot-postgres
|
||||||
|
- penpot-redis
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
|
penpot-exporter:
|
||||||
|
image: "penpotapp/exporter:latest"
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
|
penpot-postgres:
|
||||||
|
image: "postgres:15"
|
||||||
|
restart: always
|
||||||
|
stop_signal: SIGINT
|
||||||
|
volumes:
|
||||||
|
- penpot_postgres_v15:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
|
penpot-redis:
|
||||||
|
image: redis:7
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- penpot
|
||||||
29
scripts/backup.sh
Normal file
29
scripts/backup.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit immediately if a command exits with a non-zero status
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BACKUP_DIR="./backups"
|
||||||
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||||
|
DB_BACKUP_FILE="${BACKUP_DIR}/penpot_db_${TIMESTAMP}.sql"
|
||||||
|
ASSETS_BACKUP_FILE="${BACKUP_DIR}/penpot_assets_${TIMESTAMP}.tar.gz"
|
||||||
|
|
||||||
|
echo "=== Starting Penpot Backup ($TIMESTAMP) ==="
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup PostgreSQL Database
|
||||||
|
echo "Backing up Database..."
|
||||||
|
docker compose exec -T penpot-postgres pg_dump -U penpot -d penpot -c > "$DB_BACKUP_FILE"
|
||||||
|
echo "Database backed up to $DB_BACKUP_FILE"
|
||||||
|
|
||||||
|
# Backup Assets Volume
|
||||||
|
echo "Backing up Assets..."
|
||||||
|
docker compose run --rm \
|
||||||
|
-v $(pwd)/backups:/backups \
|
||||||
|
penpot-backend \
|
||||||
|
tar czvf /backups/penpot_assets_${TIMESTAMP}.tar.gz -C /opt/data/assets .
|
||||||
|
|
||||||
|
echo "Assets backed up to $ASSETS_BACKUP_FILE"
|
||||||
|
|
||||||
|
echo "=== Backup Complete! ==="
|
||||||
51
scripts/restore.sh
Normal file
51
scripts/restore.sh
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit immediately if a command exits with a non-zero status
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
echo "Usage: $0 <path_to_db_backup.sql> <path_to_assets_backup.tar.gz>"
|
||||||
|
echo "Example: $0 backups/penpot_db_20231026_120000.sql backups/penpot_assets_20231026_120000.tar.gz"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DB_FILE=$1
|
||||||
|
ASSETS_FILE=$2
|
||||||
|
|
||||||
|
# Verify files exist
|
||||||
|
if [ ! -f "$DB_FILE" ]; then
|
||||||
|
echo "Error: Database backup file '$DB_FILE' not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$ASSETS_FILE" ]; then
|
||||||
|
echo "Error: Assets backup file '$ASSETS_FILE' not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Starting Penpot Restore ==="
|
||||||
|
|
||||||
|
echo "Stopping frontend, backend, and exporter..."
|
||||||
|
docker compose stop penpot-frontend penpot-backend penpot-exporter
|
||||||
|
|
||||||
|
echo "Restoring Database from $DB_FILE..."
|
||||||
|
cat "$DB_FILE" | docker compose exec -T penpot-postgres psql -U penpot -d penpot
|
||||||
|
echo "Database restored."
|
||||||
|
|
||||||
|
# We spin up a temporary container, delete current assets, and extract the backup
|
||||||
|
# Convert relative path of ASSETS_FILE to absolute path for the volume mount
|
||||||
|
echo "Restoring Assets from $ASSETS_FILE..."
|
||||||
|
ABS_ASSETS_FILE=$(realpath "$ASSETS_FILE")
|
||||||
|
ABS_ASSETS_DIR=$(dirname "$ABS_ASSETS_FILE")
|
||||||
|
ASSETS_FILENAME=$(basename "$ABS_ASSETS_FILE")
|
||||||
|
|
||||||
|
docker compose run --rm \
|
||||||
|
-v "$ABS_ASSETS_DIR":/backups \
|
||||||
|
penpot-backend \
|
||||||
|
sh -c "rm -rf /opt/data/assets/* && tar xzvf /backups/$ASSETS_FILENAME -C /opt/data/assets/"
|
||||||
|
echo "Assets restored."
|
||||||
|
|
||||||
|
echo "Restarting all Penpot services..."
|
||||||
|
docker compose start
|
||||||
|
|
||||||
|
echo "=== Restore Complete! ==="
|
||||||
12
scripts/update.sh
Normal file
12
scripts/update.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Pulling latest Penpot images..."
|
||||||
|
docker compose pull
|
||||||
|
|
||||||
|
echo "Recreating containers..."
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
echo "Removing old unused images..."
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
echo "Penpot update complete!"
|
||||||
Reference in New Issue
Block a user