317 lines
9.0 KiB
Bash
317 lines
9.0 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Copyright (c) 2021-2026 community-scripts ORG
|
|
# Author: dave-yap (dave-yap) | Co-Author: remz1337
|
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
# Source: https://zitadel.com/
|
|
|
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
|
color
|
|
verb_ip6
|
|
catch_errors
|
|
setting_up_container
|
|
network_check
|
|
update_os
|
|
|
|
# Configuration variables
|
|
ZITADEL_DIR="/opt/zitadel"
|
|
LOGIN_DIR="/opt/login"
|
|
CONFIG_DIR="/etc/zitadel"
|
|
ZITADEL_USER="zitadel"
|
|
ZITADEL_GROUP="zitadel"
|
|
DB_NAME="zitadel"
|
|
DB_USER="zitadel"
|
|
DB_PASSWORD="$(openssl rand -base64 32 | tr -d '=/+' | head -c 32)"
|
|
POSTGRES_ADMIN_PASSWORD="$(openssl rand -base64 32 | tr -d '=/+' | head -c 32)"
|
|
MASTERKEY="$(openssl rand -base64 32 | tr -d '=/+' | head -c 32)"
|
|
API_PORT="8080"
|
|
LOGIN_PORT="3000"
|
|
|
|
# Detect server IP address
|
|
SERVER_IP=$(hostname -I | awk '{print $1}')
|
|
|
|
# Create zitadel user
|
|
msg_info "Creating zitadel system user"
|
|
groupadd --system "${ZITADEL_GROUP}"
|
|
useradd --system --gid "${ZITADEL_GROUP}" --shell /bin/bash --home-dir "${ZITADEL_DIR}" "${ZITADEL_USER}"
|
|
msg_ok "Created zitadel system user"
|
|
|
|
fetch_and_deploy_gh_release "zitadel" "zitadel/zitadel" "prebuild" "latest" "${ZITADEL_DIR}" "zitadel-linux-amd64.tar.gz"
|
|
chown -R "${ZITADEL_USER}:${ZITADEL_GROUP}" "${ZITADEL_DIR}"
|
|
|
|
fetch_and_deploy_gh_release "login" "zitadel/zitadel" "prebuild" "latest" "${LOGIN_DIR}" "zitadel-login.tar.gz"
|
|
chown -R "${ZITADEL_USER}:${ZITADEL_GROUP}" "${LOGIN_DIR}"
|
|
|
|
NODE_VERSION="24" setup_nodejs
|
|
|
|
PG_VERSION="17" setup_postgresql
|
|
|
|
setup_go
|
|
|
|
msg_info "Configuring Postgresql"
|
|
$STD sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '${POSTGRES_ADMIN_PASSWORD}';"
|
|
msg_ok "Configured PostgreSQL"
|
|
|
|
msg_info "Installing Zitadel"
|
|
cd "${ZITADEL_DIR}"
|
|
mkdir -p ${CONFIG_DIR}
|
|
echo -n "${MASTERKEY}" > ${CONFIG_DIR}/.masterkey
|
|
chmod 600 "${CONFIG_DIR}/.masterkey"
|
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/.masterkey"
|
|
|
|
# Update config.yaml for network access
|
|
cat > "${CONFIG_DIR}/config.yaml" <<EOF
|
|
ExternalSecure: false
|
|
ExternalDomain: ${SERVER_IP}
|
|
ExternalPort: ${API_PORT}
|
|
|
|
TLS:
|
|
Enabled: false
|
|
|
|
Log:
|
|
Level: info
|
|
Formatter:
|
|
Format: text
|
|
|
|
Database:
|
|
Postgres:
|
|
Database: ${DB_NAME}
|
|
Host: localhost
|
|
Port: 5432
|
|
AwaitInitialConn: 5m
|
|
MaxOpenConns: 20
|
|
MaxIdleConns: 20
|
|
ConnMaxLifetime: 60m
|
|
ConnMaxIdleTime: 10m
|
|
User:
|
|
Username: ${DB_USER}
|
|
Password: ${DB_PASSWORD}
|
|
SSL:
|
|
Mode: disable
|
|
Admin:
|
|
Username: postgres
|
|
Password: ${POSTGRES_ADMIN_PASSWORD}
|
|
SSL:
|
|
Mode: disable
|
|
|
|
FirstInstance:
|
|
LoginClientPatPath: login-client.pat
|
|
PatPath: admin.pat
|
|
InstanceName: ZITADEL
|
|
DefaultLanguage: en
|
|
Org:
|
|
LoginClient:
|
|
Machine:
|
|
Username: login-client
|
|
Name: Automatically Initialized IAM Login Client
|
|
Pat:
|
|
ExpirationDate: 2099-01-01T00:00:00Z
|
|
Machine:
|
|
Machine:
|
|
Username: admin
|
|
Name: Automatically Initialized IAM admin Client
|
|
Pat:
|
|
ExpirationDate: 2099-01-01T00:00:00Z
|
|
Human:
|
|
Username: zitadel-admin@zitadel.localhost
|
|
Password: Password1!
|
|
PasswordChangeRequired: false
|
|
|
|
DefaultInstance:
|
|
Features:
|
|
LoginV2:
|
|
BaseURI: http://${SERVER_IP}:${LOGIN_PORT}/ui/v2/login
|
|
EOF
|
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/config.yaml"
|
|
|
|
# Initialize database as zitadel user (no masterkey needed for init)
|
|
$STD sudo -u ${ZITADEL_USER} ./zitadel init --config ${CONFIG_DIR}/config.yaml
|
|
|
|
# Run setup phase as zitadel user (with masterkey and steps)
|
|
$STD sudo -u ${ZITADEL_USER} ./zitadel setup --config ${CONFIG_DIR}/config.yaml --steps ${CONFIG_DIR}/config.yaml --masterkey "${MASTERKEY}"
|
|
|
|
#Read client token
|
|
CLIENT_PAT=$(cat ${ZITADEL_DIR}/login-client.pat)
|
|
|
|
# Update Login V2 login.env file
|
|
cat > "${CONFIG_DIR}/login.env" <<EOF
|
|
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
|
EMAIL_VERIFICATION=false
|
|
ZITADEL_API_URL=http://${SERVER_IP}:${API_PORT}
|
|
ZITADEL_SERVICE_USER_TOKEN_FILE=../../login-client.pat
|
|
ZITADEL_SERVICE_USER_TOKEN=${CLIENT_PAT}
|
|
EOF
|
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/login.env"
|
|
|
|
# Create api.env file
|
|
cat > "${CONFIG_DIR}/api.env" <<EOF
|
|
ZITADEL_MASTERKEY=${MASTERKEY}
|
|
ZITADEL_DATABASE_POSTGRES_HOST=localhost
|
|
ZITADEL_DATABASE_POSTGRES_PORT=5432
|
|
ZITADEL_DATABASE_POSTGRES_DATABASE=${DB_NAME}
|
|
ZITADEL_DATABASE_POSTGRES_USER_USERNAME=${DB_USER}
|
|
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=${DB_PASSWORD}
|
|
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable
|
|
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=postgres
|
|
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=${POSTGRES_ADMIN_PASSWORD}
|
|
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable
|
|
ZITADEL_EXTERNALSECURE=false
|
|
EOF
|
|
|
|
# Set secure permissions
|
|
chmod 600 "${CONFIG_DIR}/api.env"
|
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/api.env"
|
|
msg_ok "Installed Zitadel"
|
|
|
|
msg_info "Creating Services"
|
|
# Create API service
|
|
cat > /etc/systemd/system/zitadel-api.service <<EOF
|
|
[Unit]
|
|
Description=ZITADEL API Server
|
|
After=network.target postgresql.service
|
|
Requires=postgresql.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=${ZITADEL_USER}
|
|
Group=${ZITADEL_GROUP}
|
|
WorkingDirectory=${ZITADEL_DIR}
|
|
EnvironmentFile=${CONFIG_DIR}/api.env
|
|
Environment="PATH=/usr/local/bin:/usr/local/go/bin:/usr/bin:/bin"
|
|
ExecStart=${ZITADEL_DIR}/zitadel start --config ${CONFIG_DIR}/config.yaml --masterkeyFile ${CONFIG_DIR}/.masterkey
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Create Login V2 service
|
|
cat > /etc/systemd/system/zitadel-login.service <<EOF
|
|
[Unit]
|
|
Description=ZITADEL Login V2 Service
|
|
After=network.target zitadel-api.service
|
|
Requires=zitadel-api.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=${ZITADEL_USER}
|
|
Group=${ZITADEL_GROUP}
|
|
WorkingDirectory=${LOGIN_DIR}/apps/login
|
|
EnvironmentFile=${CONFIG_DIR}/login.env
|
|
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
|
|
Environment="NODE_ENV=production"
|
|
ExecStart=node ${LOGIN_DIR}/apps/login/server.js
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Enable and start API service
|
|
systemctl enable -q --now zitadel-api.service
|
|
|
|
# Wait for API to start
|
|
sleep 5
|
|
|
|
# Enable and start Login service
|
|
systemctl enable -q --now zitadel-login
|
|
msg_ok "Created Services"
|
|
|
|
msg_info "Saving Credentials"
|
|
# Create credentials file
|
|
cat > "${CONFIG_DIR}/INSTALLATION_INFO.txt" <<EOF
|
|
################################################################################
|
|
# ZITADEL Installation Information
|
|
# Generated: $(date)
|
|
################################################################################
|
|
|
|
SERVER INFORMATION:
|
|
-------------------
|
|
Server IP: ${SERVER_IP}
|
|
API Port: ${API_PORT}
|
|
Login Port: ${LOGIN_PORT}
|
|
|
|
ACCESS URLS:
|
|
------------
|
|
Management Console: http://${SERVER_IP}:${API_PORT}/ui/console
|
|
Login V2 UI: http://${SERVER_IP}:${LOGIN_PORT}/ui/v2/login
|
|
API Endpoint: http://${SERVER_IP}:${API_PORT}
|
|
|
|
DEFAULT ADMIN CREDENTIALS:
|
|
--------------------------
|
|
Username: zitadel-admin@zitadel.localhost
|
|
Password: Password1!
|
|
|
|
IMPORTANT: Change this password immediately after first login!
|
|
|
|
DATABASE CREDENTIALS:
|
|
---------------------
|
|
Database Name: ${DB_NAME}
|
|
Database User: ${DB_USER}
|
|
Database Password: ${DB_PASSWORD}
|
|
PostgreSQL Admin Password: ${POSTGRES_ADMIN_PASSWORD}
|
|
|
|
SECURITY:
|
|
---------
|
|
Master Key: ${MASTERKEY}
|
|
|
|
IMPORTANT: Keep these credentials secure and backup this file!
|
|
|
|
VERIFICATION:
|
|
-------------
|
|
1. Check API health:
|
|
curl http://${SERVER_IP}:${API_PORT}/debug/healthz
|
|
2. Access Management Console:
|
|
http://${SERVER_IP}:${API_PORT}/ui/console
|
|
3. Login with admin credentials above
|
|
|
|
DATABASE INFORMATION:
|
|
--------------------
|
|
The database and user are automatically created by ZITADEL on first startup.
|
|
ZITADEL uses the admin credentials to create:
|
|
- Database: ${DB_NAME}
|
|
- User: ${DB_USER}
|
|
- Schemas: eventstore, projections, system
|
|
|
|
PRODUCTION NOTES:
|
|
-----------------
|
|
1. This installation uses HTTP (not HTTPS) for simplicity
|
|
2. For production with HTTPS:
|
|
- Set ExternalSecure: true in config.yaml
|
|
- Configure TLS certificates
|
|
- Update firewall rules for port 443
|
|
3. Change all default passwords immediately
|
|
4. Set up regular database backups
|
|
5. Configure proper monitoring and alerting
|
|
6. Review and harden PostgreSQL security settings
|
|
|
|
BACKUP COMMANDS:
|
|
----------------
|
|
Database backup:
|
|
PGPASSWORD=${DB_PASSWORD} pg_dump -h localhost -U ${DB_USER} ${DB_NAME} > zitadel_backup_\$(date +%Y%m%d).sql
|
|
|
|
Database restore:
|
|
PGPASSWORD=${DB_PASSWORD} psql -h localhost -U ${DB_USER} ${DB_NAME} < zitadel_backup_YYYYMMDD.sql
|
|
|
|
################################################################################
|
|
EOF
|
|
chmod 600 "${CONFIG_DIR}/INSTALLATION_INFO.txt"
|
|
chown "${ZITADEL_USER}:${ZITADEL_GROUP}" "${CONFIG_DIR}/INSTALLATION_INFO.txt"
|
|
cp ${ZITADEL_DIR}/admin.pat ${CONFIG_DIR}/admin.pat.BAK
|
|
cp ${ZITADEL_DIR}/login-client.pat ${CONFIG_DIR}/login-client.pat.BAK
|
|
msg_ok "Saved Credentials"
|
|
|
|
msg_info "Create zitadel-rerun.sh"
|
|
cat <<EOF >~/zitadel-rerun.sh
|
|
systemctl stop zitadel-api zitadel-login
|
|
timeout --kill-after=5s 15s /opt/zitadel/zitadel setup --masterkeyFile ${CONFIG_DIR}/.masterkey --config ${CONFIG_DIR}/config.yaml
|
|
systemctl restart zitadel-api zitadel-login
|
|
EOF
|
|
msg_ok "Bash script for rerunning Zitadel after changing Zitadel config.yaml"
|
|
|
|
motd_ssh
|
|
customize
|
|
cleanup_lxc
|