onedev 搭建
OneDev是一个开源的一体化的DevOps平台,原生支持Docker, 详情详见 https://github.com/theonedev/onedev
#!/usr/bin/env bash
#
# OneDev installer for Debian 13
# Supports:
# 1) Docker Compose + PostgreSQL (recommended)
# 2) Bare-metal/binary + PostgreSQL + systemd
#
# Usage:
# chmod +x install-onedev.sh
# ./install-onedev.sh docker
# ./install-onedev.sh binary
# ./install-onedev.sh nginx
# ./install-onedev.sh config
#
# All important deployment parameters are centralized below and may also
# be overridden with environment variables.
#
set -Eeuo pipefail
IFS=$'\n\t'
umask 027
###############################################################################
# User variables
###############################################################################
# Main install directory.
# Docker mode: compose.yml, data/, secrets/, backup/ are created here.
# Binary mode: OneDev program itself is extracted here.
INSTALL_DIR="${INSTALL_DIR:-/opt/Docker/OneDev}"
# Public DNS name used by Nginx and displayed in the final setup hints.
DOMAIN="${DOMAIN}"
# Public/host SSH port for OneDev Git SSH.
# If set to 22, move the Debian system sshd to another port BEFORE installing.
ONEDEV_SSH_PORT="${ONEDEV_SSH_PORT:-22}"
# Host/bare-metal HTTP port used by OneDev.
# Nginx proxies HTTPS traffic to 127.0.0.1:${ONEDEV_WEB_PORT}.
ONEDEV_WEB_PORT="${ONEDEV_WEB_PORT:-6610}"
# Bind OneDev Web only to localhost when Docker is used.
# Binary mode writes this value to conf/server.properties as http_host.
ONEDEV_WEB_BIND="${ONEDEV_WEB_BIND:-127.0.0.1}"
# Production database settings.
POSTGRES_MAJOR="${POSTGRES_MAJOR:-17}"
DB_NAME="${DB_NAME:-onedev}"
DB_USER="${DB_USER:-onedev}"
# Leave empty to generate/preserve a random password in:
# ${INSTALL_DIR}/secrets/postgres_password
DB_PASSWORD="${DB_PASSWORD:-}"
# Bare-metal service account.
ONEDEV_USER="${ONEDEV_USER:-onedev}"
ONEDEV_GROUP="${ONEDEV_GROUP:-onedev}"
# Official latest bare-metal package.
ONEDEV_DOWNLOAD_URL="${ONEDEV_DOWNLOAD_URL:-https://code.onedev.io/onedev/server/~site/onedev-latest.tar.gz}"
# Docker image intentionally has NO version tag.
ONEDEV_DOCKER_IMAGE="${ONEDEV_DOCKER_IMAGE:-1dev/server}"
# Nginx configuration is generated, but not automatically installed/reloaded.
GENERATE_NGINX_CONFIG="${GENERATE_NGINX_CONFIG:-yes}"
SSL_CERT_PATH="${SSL_CERT_PATH:-/etc/letsencrypt/live/${DOMAIN}/fullchain.pem}"
SSL_KEY_PATH="${SSL_KEY_PATH:-/etc/letsencrypt/live/${DOMAIN}/privkey.pem}"
# Whether Docker mode should mount /var/run/docker.sock into OneDev.
# "no" is safer for a production server; use a OneDev Agent for container CI.
MOUNT_DOCKER_SOCKET="${MOUNT_DOCKER_SOCKET:-no}"
###############################################################################
# Derived paths
###############################################################################
COMPOSE_FILE="${INSTALL_DIR}/compose.yml"
DATA_DIR="${INSTALL_DIR}/data"
ONEDEV_DATA_DIR="${DATA_DIR}/onedev"
POSTGRES_DATA_DIR="${DATA_DIR}/postgres"
SECRETS_DIR="${INSTALL_DIR}/secrets"
BACKUP_DIR="${INSTALL_DIR}/backup"
DB_PASSWORD_FILE="${SECRETS_DIR}/postgres_password"
NGINX_DIR="${INSTALL_DIR}/nginx"
NGINX_CONF_OUTPUT="${NGINX_DIR}/${DOMAIN}.conf"
###############################################################################
# Helpers
###############################################################################
C_RESET='\033[0m'
C_GREEN='\033[0;32m'
C_YELLOW='\033[0;33m'
C_RED='\033[0;31m'
C_BLUE='\033[0;34m'
log() { printf "${C_GREEN}[INFO]${C_RESET} %s\n" "$*"; }
warn() { printf "${C_YELLOW}[WARN]${C_RESET} %s\n" "$*" >&2; }
err() { printf "${C_RED}[ERROR]${C_RESET} %s\n" "$*" >&2; }
die() { err "$*"; exit 1; }
trap 'err "Installation failed at line ${LINENO}. Command: ${BASH_COMMAND}"' ERR
require_root() {
[[ ${EUID} -eq 0 ]] || die "Please run this script as root."
}
check_debian() {
[[ -r /etc/os-release ]] || die "/etc/os-release not found."
# shellcheck disable=SC1091
. /etc/os-release
[[ "${ID:-}" == "debian" ]] || die "This installer targets Debian. Detected: ${ID:-unknown}"
local major="${VERSION_ID%%.*}"
[[ "$major" =~ ^[0-9]+$ ]] || die "Unable to determine Debian version."
if (( major < 13 )); then
warn "Detected Debian ${VERSION_ID}. This script is designed and tested for Debian 13."
fi
}
validate_port() {
local p="$1" name="$2"
[[ "$p" =~ ^[0-9]+$ ]] || die "${name} must be an integer."
(( p >= 1 && p <= 65535 )) || die "${name} must be between 1 and 65535."
}
validate_name() {
local value="$1" name="$2"
[[ "$value" =~ ^[a-zA-Z_][a-zA-Z0-9_-]*$ ]] || \
die "${name} contains unsupported characters: ${value}"
}
validate_config() {
[[ "$INSTALL_DIR" == /* ]] || die "INSTALL_DIR must be an absolute path."
[[ -n "$DOMAIN" && "$DOMAIN" != *" "* ]] || die "DOMAIN is invalid."
validate_port "$ONEDEV_SSH_PORT" "ONEDEV_SSH_PORT"
validate_port "$ONEDEV_WEB_PORT" "ONEDEV_WEB_PORT"
[[ "$ONEDEV_SSH_PORT" != "$ONEDEV_WEB_PORT" ]] || \
die "ONEDEV_SSH_PORT and ONEDEV_WEB_PORT cannot be the same."
validate_name "$DB_NAME" "DB_NAME"
validate_name "$DB_USER" "DB_USER"
validate_name "$ONEDEV_USER" "ONEDEV_USER"
validate_name "$ONEDEV_GROUP" "ONEDEV_GROUP"
}
port_in_use() {
local port="$1"
ss -H -ltn 2>/dev/null | awk '{print $4}' | grep -Eq ":${port}$"
}
check_required_ports() {
local mode="$1"
if port_in_use "$ONEDEV_SSH_PORT"; then
die "TCP port ${ONEDEV_SSH_PORT} is already in use. If it is Debian sshd, move the system SSH service to another port first."
fi
if port_in_use "$ONEDEV_WEB_PORT"; then
die "TCP port ${ONEDEV_WEB_PORT} is already in use."
fi
if [[ "$mode" == "binary" && "$ONEDEV_SSH_PORT" -lt 1024 ]]; then
log "Binary mode will grant only CAP_NET_BIND_SERVICE to the OneDev systemd service so user '${ONEDEV_USER}' can bind TCP/${ONEDEV_SSH_PORT}."
fi
}
apt_update_once() {
if [[ "${APT_UPDATED:-no}" != "yes" ]]; then
apt-get update
APT_UPDATED=yes
fi
}
install_common_tools() {
apt_update_once
DEBIAN_FRONTEND=noninteractive apt-get install -y \
ca-certificates curl git openssl tar gzip xz-utils \
gnupg lsb-release iproute2
}
ensure_layout() {
install -d -m 0750 "$INSTALL_DIR" "$SECRETS_DIR" "$BACKUP_DIR"
}
ensure_db_password() {
ensure_layout
if [[ -n "$DB_PASSWORD" ]]; then
printf '%s\n' "$DB_PASSWORD" > "$DB_PASSWORD_FILE"
chmod 0600 "$DB_PASSWORD_FILE"
return
fi
if [[ -s "$DB_PASSWORD_FILE" ]]; then
DB_PASSWORD="$(tr -d '\r\n' < "$DB_PASSWORD_FILE")"
[[ -n "$DB_PASSWORD" ]] || die "Database password file is empty: $DB_PASSWORD_FILE"
return
fi
DB_PASSWORD="$(openssl rand -hex 32)"
printf '%s\n' "$DB_PASSWORD" > "$DB_PASSWORD_FILE"
chmod 0600 "$DB_PASSWORD_FILE"
}
server_url() {
printf 'https://%s' "$DOMAIN"
}
ssh_root_url() {
if [[ "$ONEDEV_SSH_PORT" == "22" ]]; then
printf 'ssh://%s' "$DOMAIN"
else
printf 'ssh://%s:%s' "$DOMAIN" "$ONEDEV_SSH_PORT"
fi
}
wait_for_http() {
local url="http://127.0.0.1:${ONEDEV_WEB_PORT}/"
local i
for i in $(seq 1 120); do
if curl -fsS --max-time 3 "$url" >/dev/null 2>&1; then
log "OneDev Web is responding on ${url}"
return 0
fi
sleep 2
done
warn "OneDev did not answer HTTP health checks. Check service/container logs."
return 1
}
###############################################################################
# Docker installation
###############################################################################
install_docker_engine() {
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
log "Docker Engine and Docker Compose plugin are already installed."
systemctl enable --now docker >/dev/null 2>&1 || true
return
fi
log "Installing Docker Engine from Docker's official Debian repository..."
apt_update_once
DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl
# Remove known conflicting distribution packages only when Docker CE is not
# already usable. Existing images/data under /var/lib/docker are not deleted.
DEBIAN_FRONTEND=noninteractive apt-get remove -y \
docker.io docker-compose docker-doc docker-buildx podman-docker \
containerd runc 2>/dev/null || true
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg \
-o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# shellcheck disable=SC1091
. /etc/os-release
cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: ${VERSION_CODENAME}
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker
docker version >/dev/null
docker compose version >/dev/null
log "Docker Engine installed successfully."
}
write_compose_file() {
local docker_socket_line=""
if [[ "$MOUNT_DOCKER_SOCKET" == "yes" ]]; then
docker_socket_line=' - /var/run/docker.sock:/var/run/docker.sock'
fi
install -d -m 0750 \
"$DATA_DIR" "$ONEDEV_DATA_DIR" "$POSTGRES_DATA_DIR" \
"$SECRETS_DIR" "$BACKUP_DIR"
cat > "$COMPOSE_FILE" <<EOF
services:
postgres:
image: postgres:${POSTGRES_MAJOR}
container_name: onedev-postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
secrets:
- postgres_password
volumes:
- ./data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
networks:
- onedev
onedev:
image: ${ONEDEV_DOCKER_IMAGE}
container_name: onedev
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
hibernate_dialect: io.onedev.server.persistence.PostgreSQLDialect
hibernate_connection_driver_class: org.postgresql.Driver
hibernate_connection_url: jdbc:postgresql://postgres:5432/${DB_NAME}
hibernate_connection_username: ${DB_USER}
hibernate_connection_password_file: /run/secrets/postgres_password
secrets:
- postgres_password
volumes:
- ./data/onedev:/opt/onedev
${docker_socket_line}
ports:
- "${ONEDEV_WEB_BIND}:${ONEDEV_WEB_PORT}:6610"
- "${ONEDEV_SSH_PORT}:6611"
ulimits:
nofile:
soft: 65536
hard: 65536
stop_grace_period: 2m
networks:
- onedev
networks:
onedev:
driver: bridge
secrets:
postgres_password:
file: ./secrets/postgres_password
EOF
chmod 0640 "$COMPOSE_FILE"
}
install_docker_mode() {
require_root
check_debian
validate_config
install_common_tools
if [[ -e "$COMPOSE_FILE" ]]; then
die "${COMPOSE_FILE} already exists. Refusing to overwrite an existing deployment."
fi
check_required_ports docker
ensure_db_password
install_docker_engine
log "Generating Docker Compose deployment..."
write_compose_file
(
cd "$INSTALL_DIR"
docker compose config -q
docker compose pull
docker compose up -d
)
if [[ "$GENERATE_NGINX_CONFIG" == "yes" ]]; then
generate_nginx_config
fi
wait_for_http || true
log "Docker deployment completed."
print_post_install docker
}
###############################################################################
# Binary / bare-metal installation
###############################################################################
install_binary_dependencies() {
apt_update_once
DEBIAN_FRONTEND=noninteractive apt-get install -y \
default-jre-headless git curl postgresql postgresql-client \
ca-certificates openssl tar gzip
systemctl enable --now postgresql
}
create_onedev_user() {
if ! getent group "$ONEDEV_GROUP" >/dev/null; then
groupadd --system "$ONEDEV_GROUP"
fi
if ! id "$ONEDEV_USER" >/dev/null 2>&1; then
useradd \
--system \
--gid "$ONEDEV_GROUP" \
--home-dir "$INSTALL_DIR" \
--shell /usr/sbin/nologin \
"$ONEDEV_USER"
fi
}
setup_local_postgres() {
ensure_db_password
log "Preparing PostgreSQL database '${DB_NAME}' and role '${DB_USER}'..."
if runuser -u postgres -- psql -tAc \
"SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" | grep -q 1; then
printf "ALTER ROLE %s WITH LOGIN PASSWORD :'dbpass';\n" "$DB_USER" | \
runuser -u postgres -- psql \
-v ON_ERROR_STOP=1 \
-v dbpass="$DB_PASSWORD" \
>/dev/null
else
printf "CREATE ROLE %s WITH LOGIN PASSWORD :'dbpass';\n" "$DB_USER" | \
runuser -u postgres -- psql \
-v ON_ERROR_STOP=1 \
-v dbpass="$DB_PASSWORD" \
>/dev/null
fi
if ! runuser -u postgres -- psql -tAc \
"SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" | grep -q 1; then
runuser -u postgres -- createdb -O "$DB_USER" "$DB_NAME"
fi
}
download_and_extract_onedev() {
[[ ! -e "${INSTALL_DIR}/bin/server.sh" ]] || \
die "OneDev already appears to be installed at ${INSTALL_DIR}."
local tmpdir archive first_component
tmpdir="$(mktemp -d)"
archive="${tmpdir}/onedev-latest.tar.gz"
log "Downloading latest OneDev bare-metal package..."
curl -fL --retry 3 --retry-delay 2 \
"$ONEDEV_DOWNLOAD_URL" \
-o "$archive"
tar -tzf "$archive" >/dev/null
first_component="$(
tar -tzf "$archive" |
head -n1 |
cut -d/ -f1
)"
[[ -n "$first_component" ]] || die "Unable to inspect OneDev archive."
install -d -m 0750 "$INSTALL_DIR"
# Official archive contains a single top-level onedev-<version> directory.
tar -xzf "$archive" -C "$INSTALL_DIR" --strip-components=1
rm -rf "$tmpdir"
[[ -x "${INSTALL_DIR}/bin/server.sh" ]] || \
die "Extracted package does not contain bin/server.sh."
}
set_property() {
local file="$1" key="$2" value="$3"
if grep -Eq "^[[:space:]]*${key}=" "$file"; then
sed -ri "s|^[[:space:]]*${key}=.*|${key}=${value}|" "$file"
else
printf '\n%s=%s\n' "$key" "$value" >> "$file"
fi
}
configure_binary_ports() {
local file="${INSTALL_DIR}/conf/server.properties"
[[ -f "$file" ]] || die "Missing ${file}"
set_property "$file" "http_host" "$ONEDEV_WEB_BIND"
set_property "$file" "http_port" "$ONEDEV_WEB_PORT"
set_property "$file" "ssh_port" "$ONEDEV_SSH_PORT"
}
configure_binary_database() {
local file="${INSTALL_DIR}/conf/hibernate.properties"
[[ -f "$file" ]] || die "Missing ${file}"
# Recreate this file with the official PostgreSQL dialect and the standard
# Hikari/cache settings shipped by OneDev.
cat > "$file" <<EOF
# Generated by install-onedev.sh
hibernate.dialect=io.onedev.server.persistence.PostgreSQLDialect
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.connection.url=jdbc:postgresql://127.0.0.1:5432/${DB_NAME}
hibernate.connection.username=${DB_USER}
hibernate.connection.password=${DB_PASSWORD}
hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
hibernate.hikari.transactionIsolation=TRANSACTION_READ_COMMITTED
hibernate.hikari.autoCommit=true
hibernate.hikari.maximumPoolSize=25
hibernate.show_sql=false
hibernate.format_sql=true
javax.persistence.validation.mode=none
hibernate.validator.apply_to_ddl=false
hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastLocalCacheRegionFactory
hibernate.cache.use_query_cache=true
hibernate.cache.auto_evict_collection_cache=true
hibernate.query.plan_cache_max_size=2048
hibernate.query.plan_parameter_metadata_max_size=128
EOF
chmod 0600 "$file"
}
install_binary_systemd_service() {
local capability_lines=""
if (( ONEDEV_SSH_PORT < 1024 || ONEDEV_WEB_PORT < 1024 )); then
capability_lines=$'AmbientCapabilities=CAP_NET_BIND_SERVICE\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE'
fi
cat > /etc/systemd/system/onedev.service <<EOF
[Unit]
Description=OneDev Server
Wants=network-online.target
After=network-online.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
User=${ONEDEV_USER}
Group=${ONEDEV_GROUP}
WorkingDirectory=${INSTALL_DIR}
ExecStart=${INSTALL_DIR}/bin/server.sh console
Restart=on-failure
RestartSec=10
TimeoutStopSec=120
LimitNOFILE=65536
${capability_lines}
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now onedev
}
install_binary_mode() {
require_root
check_debian
validate_config
install_common_tools
[[ ! -e "${INSTALL_DIR}/bin/server.sh" ]] || \
die "Existing binary OneDev installation detected at ${INSTALL_DIR}."
check_required_ports binary
install_binary_dependencies
create_onedev_user
ensure_db_password
setup_local_postgres
download_and_extract_onedev
configure_binary_ports
configure_binary_database
# OneDev needs full write access to its installation directory.
chown -R "${ONEDEV_USER}:${ONEDEV_GROUP}" "$INSTALL_DIR"
chmod 0700 "$SECRETS_DIR"
chmod 0600 "$DB_PASSWORD_FILE"
install_binary_systemd_service
if [[ "$GENERATE_NGINX_CONFIG" == "yes" ]]; then
generate_nginx_config
chown -R "${ONEDEV_USER}:${ONEDEV_GROUP}" "$NGINX_DIR" 2>/dev/null || true
fi
wait_for_http || {
systemctl status onedev --no-pager || true
journalctl -u onedev -n 100 --no-pager || true
}
log "Binary deployment completed."
print_post_install binary
}
###############################################################################
# Nginx configuration generator
###############################################################################
generate_nginx_config() {
install -d -m 0750 "$NGINX_DIR"
cat > "$NGINX_CONF_OUTPUT" <<EOF
# OneDev reverse proxy generated by install-onedev.sh
# Copy/include this file from your Nginx vhost configuration after confirming
# that SSL_CERT_PATH and SSL_KEY_PATH exist.
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name ${DOMAIN};
ssl_certificate ${SSL_CERT_PATH};
ssl_certificate_key ${SSL_KEY_PATH};
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
client_max_body_size 0;
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
location /wicket/websocket {
proxy_pass http://127.0.0.1:${ONEDEV_WEB_PORT}/wicket/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_read_timeout 1800s;
}
location /~server {
proxy_pass http://127.0.0.1:${ONEDEV_WEB_PORT}/~server;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location /~api/streaming {
proxy_pass http://127.0.0.1:${ONEDEV_WEB_PORT}/~api/streaming;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location / {
proxy_pass http://127.0.0.1:${ONEDEV_WEB_PORT};
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_buffering off;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
server {
listen 80;
listen [::]:80;
server_name ${DOMAIN};
return 301 https://\$host\$request_uri;
}
EOF
chmod 0640 "$NGINX_CONF_OUTPUT"
log "Nginx configuration generated: ${NGINX_CONF_OUTPUT}"
if [[ ! -f "$SSL_CERT_PATH" || ! -f "$SSL_KEY_PATH" ]]; then
warn "TLS certificate/key not found at the configured paths. Obtain/install the certificate before enabling this Nginx vhost."
fi
}
###############################################################################
# Output / CLI
###############################################################################
print_config() {
cat <<EOF
OneDev installer configuration
------------------------------
INSTALL_DIR = ${INSTALL_DIR}
DOMAIN = ${DOMAIN}
ONEDEV_SSH_PORT = ${ONEDEV_SSH_PORT}
ONEDEV_WEB_PORT = ${ONEDEV_WEB_PORT}
ONEDEV_WEB_BIND = ${ONEDEV_WEB_BIND}
POSTGRES_MAJOR = ${POSTGRES_MAJOR}
DB_NAME = ${DB_NAME}
DB_USER = ${DB_USER}
ONEDEV_USER = ${ONEDEV_USER}
ONEDEV_DOCKER_IMAGE = ${ONEDEV_DOCKER_IMAGE}
MOUNT_DOCKER_SOCKET = ${MOUNT_DOCKER_SOCKET}
SERVER_URL = $(server_url)
SSH_ROOT_URL = $(ssh_root_url)
NGINX_CONF_OUTPUT = ${NGINX_CONF_OUTPUT}
EOF
}
print_post_install() {
local mode="$1"
cat <<EOF
======================================================================
OneDev installation finished
======================================================================
Mode:
${mode}
Install directory:
${INSTALL_DIR}
OneDev local Web:
http://127.0.0.1:${ONEDEV_WEB_PORT}
Public Server URL:
$(server_url)
OneDev SSH Root URL:
$(ssh_root_url)
Nginx configuration:
${NGINX_CONF_OUTPUT}
IMPORTANT:
1. If TCP/${ONEDEV_SSH_PORT} is the public Git SSH port, make sure the Debian
system sshd is NOT listening on the same port.
2. Open the public URL and finish OneDev's first-run administrator setup.
3. During first-run setup use:
Server URL: $(server_url)
SSH Root URL: $(ssh_root_url)
4. The generated Nginx file is NOT automatically enabled or reloaded.
5. PostgreSQL password is stored at:
${DB_PASSWORD_FILE}
EOF
if [[ "$mode" == "docker" ]]; then
cat <<EOF
Useful Docker commands:
cd ${INSTALL_DIR}
docker compose ps
docker compose logs -f onedev
docker compose logs -f postgres
OneDev upgrades remain explicit:
cd ${INSTALL_DIR}
docker compose pull onedev
docker compose up -d --no-deps onedev
EOF
else
cat <<EOF
Useful binary/systemd commands:
systemctl status onedev
journalctl -u onedev -f
systemctl restart onedev
EOF
fi
}
usage() {
cat <<EOF
Usage:
$0 docker
Install OneDev using Docker Compose + PostgreSQL.
$0 binary
Install latest OneDev bare-metal package + PostgreSQL + systemd.
$0 nginx
Only generate the Nginx reverse-proxy configuration.
$0 config
Print resolved variables.
Variables are defined at the top of this script and may also be overridden:
INSTALL_DIR=/opt/OneDev DOMAIN=dev.example.com \\
ONEDEV_SSH_PORT=22 ONEDEV_WEB_PORT=6610 \\
$0 docker
EOF
}
main() {
local action="${1:-}"
case "$action" in
docker)
install_docker_mode
;;
binary|baremetal|bare-metal)
install_binary_mode
;;
nginx)
require_root
validate_config
generate_nginx_config
;;
config)
validate_config
print_config
;;
-h|--help|help|"")
usage
;;
*)
usage
die "Unknown action: ${action}"
;;
esac
}
main "$@"