Linux安装OpenProject

1. 参考

  1. 官方安装文档
  2. OpenProject服务的备份与恢复
  3. 企业版工具

2. 环境

设备

  • 虚拟机 16C/32G/300G/千兆

系统

  • Ubuntu24.04 192.168.15.96

3. 安装OpenProject

采用官方推荐:Docker compose方式安装
官方安装文档

安装Docker

安装步骤,参见Ubuntu24.04 安装Docker

安装OpenProject

  1. 创建目录
bash 复制代码
mkdir -p /public/application
  1. 下载源码
bash 复制代码
cd /public/application
git clone https://github.com/opf/openproject-docker-compose.git --depth=1 --branch=stable/16 openproject
  1. 配置环境变量
bash 复制代码
cp .env.example .env
vim .env
bash 复制代码
# All environment variables defined here will only apply if you pass them
# to the OpenProject container in docker-compose.yml under x-op-app -> environment.
# For the examples here this is already the case.
#
# Please refer to our documentation to see all possible variables:
#   https://www.openproject.org/docs/installation-and-operations/configuration/environment/
#
TAG=16-slim
# 因为前端使用了nginx做代理,配置了SSL域名证书,所以需要启用HTTPS
OPENPROJECT_HTTPS=true
# 必须配置与访问域名一致,且只能配置一个(域名示例,自行修改)
OPENPROJECT_HOST__NAME="openproject.xk.com:8899"
#以下是无效配置
#OPENPROJECT_HOST__NAME="openproject.xk.com:8899,192.168.7.28:8899"
#OPENPROJECT_HOST__NAME="*"
# 关闭强制浏览器使用https
OPENPROJECT_HSTS=false
# 定义监听端口需要与OPENPROJECT_HOST__NAME保持一致
PORT=8899
OPENPROJECT_RAILS__RELATIVE__URL__ROOT=
IMAP_ENABLED=false
# 定义pg的密码
#POSTGRES_PASSWORD=yourpassword
#如果定义上述密码,需要修改以下的默认密码p4ssw0rd
DATABASE_URL=postgres://postgres:p4ssw0rd@db/openproject?pool=20&encoding=unicode&reconnect=true
RAILS_MIN_THREADS=4
RAILS_MAX_THREADS=16
# postgresql数据库目录
PGDATA="/public/application/openproject/postgresql/data"
# 文件存储目录
OPDATA="/public/application/openproject/assets"
  1. 创建服务对应目录
bash 复制代码
mkdir -p /public/application/openproject/postgresql/data
mkdir -p /public/application/openproject/assets
  1. 修改docker-compose.yml
  • 修改 postgres:17 (默认版本是13,升级为17)
bash 复制代码
vim /public/application/openproject/docker-compose.yml
bash 复制代码
......
services:
  db:
    image: postgres:17
    <<: *restart_policy
    stop_grace_period: "3s"
    volumes:
      - "${PGDATA:-pgdata}:/var/lib/postgresql/data"
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-p4ssw0rd}
      POSTGRES_DB: openproject
    networks:
      - backend
......

导入Docker镜像

  1. 查看images目录下提前导出的镜像(如果可以访问Docker Hub直接拉取镜像,可以跳过导入步骤)
bash 复制代码
tree
.
├── autoheal_1.2.0.tar
├── memcached_latest.tar
├── openproject_16-slim.tar
├── postgres_17.tar
└── proxy_latest.tar
  1. 导入Docker镜像
bash 复制代码
docker load -i autoheal_1.2.0.tar
docker load -i memcached_latest.tar
docker load -i openproject_16-slim.tar
docker load -i postgres_17.tar
docker load -i proxy_latest.tar
  1. 查看Docker镜像
bash 复制代码
docker images
bash 复制代码
# 输出结果                                                                                                                          i Info →   U  In Use
IMAGE                                                         ID             DISK USAGE   CONTENT SIZE   EXTRA
memcached:latest                                              462fa779babc        127MB         34.2MB    U   
openproject/openproject:16-slim                               1d26165952bb       5.58GB         2.72GB    U   
openproject/proxy:latest                                      390ce999ea0b       74.3MB         20.1MB    U   
postgres:17                                                   dca7512acaa1        640MB          167MB    U   
willfarrell/autoheal:1.2.0                                    31f580ef0279       13.8MB         4.31MB    U   

说明:如果使用代理软件拉取的镜像,需要使用docker tag 命令修改镜像名称,名称需要与docker-compose.yml保持一致

修改工作目录权限

  • 容器需要有操作外部挂载操作系统目录的权限(如果希望使用专用账号运行,可以修改docker compose指定专用账号运行,或修改1000:1000对应的账号)
bash 复制代码
sudo chown 1000:1000 -R /public/application/openproject

4. 测试启动OpenProject

测试启动

  • 指定OPENPROJECT_HTTPS=false,临时关闭HTTPS,然后启动服务。关闭是为了测试直接访问服务是否正常
bash 复制代码
OPENPROJECT_HOST__NAME="192.168.15.96:8899" OPENPROJECT_HTTPS=false docker compose up -d --build 
bash 复制代码
[+] Building 23.6s (10/10) FINISHED                                                                                                           
 => [internal] load local bake definitions                                                                                               0.0s
 => => reading from stdin 581B                                                                                                           0.0s
 => [internal] load build definition from Dockerfile                                                                                     0.0s
 => => transferring dockerfile: 281B                                                                                                     0.0s
 => [internal] load metadata for docker.io/library/caddy:2                                                                              23.1s
 => [internal] load .dockerignore                                                                                                        0.0s
 => => transferring context: 2B                                                                                                          0.0s
 => [internal] load build context                                                                                                        0.0s
 => => transferring context: 40B                                                                                                         0.0s
 => [1/3] FROM docker.io/library/caddy:2@sha256:dedfbbeb703b2ce9ff4a98fc06aa9c7c7d9a42f0b7d778738c1dd3ef11dcc767                         0.0s
 => => resolve docker.io/library/caddy:2@sha256:dedfbbeb703b2ce9ff4a98fc06aa9c7c7d9a42f0b7d778738c1dd3ef11dcc767                         0.0s
 => CACHED [2/3] COPY ./Caddyfile.template /etc/caddy/Caddyfile.template                                                                 0.0s
 => CACHED [3/3] RUN sed 's|${APP_HOST}|'"web"'|g' /etc/caddy/Caddyfile.template > /etc/caddy/Caddyfile                                  0.0s
 => exporting to image                                                                                                                   0.1s
 => => exporting layers                                                                                                                  0.0s
 => => exporting manifest sha256:7babeb6acbfe81a6a07df370523f0e1817d11e741094634ecd8ce8259d1cb88f                                        0.0s
 => => exporting config sha256:34cad2f332c1768c38b39a05bc89838410d369b1566cf929e9c7ec87d7162fd9                                          0.0s
 => => exporting attestation manifest sha256:cbd46b34bd570fe7c8a3718f1545fd15510665e958f770cb7375011abddad8b3                            0.0s
 => => exporting manifest list sha256:9eef94d095922b62961dee07148e26a6ac791d353462eb55378a3756816ee9d6                                   0.0s
 => => naming to docker.io/openproject/proxy:latest                                                                                      0.0s
 => => unpacking to docker.io/openproject/proxy:latest                                                                                   0.0s
 => resolving provenance for metadata file                                                                                               0.0s
[+] up 12/12
 ✔ Image openproject/proxy          Built                                                                                               23.8s 
 ✔ Network openproject_backend      Created                                                                                              0.1s 
 ✔ Network openproject_frontend     Created                                                                                              0.1s 
 ✔ Network openproject_default      Created                                                                                              0.1s 
 ✔ Container openproject-seeder-1   Created                                                                                              0.1s 
 ✔ Container openproject-cache-1    Created                                                                                              0.1s 
 ✔ Container openproject-autoheal-1 Created                                                                                              0.1s 
 ✔ Container openproject-db-1       Created                                                                                              0.1s 
 ✔ Container openproject-web-1      Created                                                                                              0.0s 
 ✔ Container openproject-worker-1   Created                                                                                              0.0s 
 ✔ Container openproject-cron-1     Created                                                                                              0.0s 
 ✔ Container openproject-proxy-1    Created                                                                                              0.1s 
  • 查看容器运行状态
bash 复制代码
docker compose ps
bash 复制代码
NAME                   IMAGE                             COMMAND                  SERVICE   CREATED      STATUS                  PORTS
openproject-cache-1    memcached                         "docker-entrypoint.s..."   cache     3 days ago   Up 31 hours             11211/tcp
openproject-cron-1     openproject/openproject:16-slim   "./docker/prod/entry..."   cron      3 days ago   Up 31 hours             8080/tcp
openproject-db-1       postgres:17                       "docker-entrypoint.s..."   db        3 days ago   Up 31 hours             5432/tcp
openproject-proxy-1    openproject/proxy                 "caddy run --config ..."   proxy     3 days ago   Up 31 hours             443/tcp, 2019/tcp, 443/udp, 0.0.0.0:8899->80/tcp, [::]:8899->80/tcp
openproject-web-1      openproject/openproject:16-slim   "./docker/prod/entry..."   web       3 days ago   Up 31 hours (healthy)   8080/tcp
openproject-worker-1   openproject/openproject:16-slim   "./docker/prod/entry..."   worker    3 days ago   Up 31 hours             8080/tcp
  • 查看容器运行日志
bash 复制代码
# -n1 查看最后一行日志(可根据需要自行修改)
docker compose logs -n1
bash 复制代码
# 日志中没有错误信息
......
worker-1  | I, [2025-12-16T09:15:00.069321 #7]  INFO -- : [GoodJob] [7] [GoodJob::Scheduler(queues=* max_threads=20)-thread-33] Executed GoodJob fdd6c446-c40a-43fe-a5ed-56bfe2e3e2fb

访问Web

  • 默认账号 admin
  • 默认密码 admin

5. 配置Nginx代理

配置Nginx代理

  • 编辑虚拟配置文件,负责接收HTTPS请求,并向上游(OpenProject服务)转发HTTP请求
bash 复制代码
# 定义upstream  
upstream  proxy_project {
            # server指令指定后端服务器的IP地址和端口
            server    192.168.15.96:8899;
          }

# HTTPS Server
server { 
           # 监听端口
           listen       8899 ssl;
           server_name  project.xk.com;
           #return 301 http://$host$request_uri;
           
           ssl_certificate      /usr/local/nginx/conf/xk-com/xk.com.pem;
           ssl_certificate_key  /usr/local/nginx/conf/xk-com/xk.com.key;
           ssl_session_cache    shared:SSL:30m;
           ssl_session_timeout 5m;
           #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!3DES;
           ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
           ssl_protocols TLSv1.2 TLSv1.3;
           ssl_prefer_server_ciphers  on;

           add_header Cache-Control no-cache;

           location / {
                       # 代理转发,服务转发
                       proxy_pass http://proxy_project;
                       
                       client_max_body_size 1000m;
                       #proxy_set_header Host $host;
                       # 设置Host $http_host,向上游服务传递域名:端口
                       proxy_set_header Host $http_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_set_header Upgrade $http_upgrade;
                       proxy_http_version 1.1;

                       proxy_connect_timeout 300;
                       proxy_read_timeout 300;
                       proxy_send_timeout 300;
                    }
        } 

加载配置生效

  • 加载Nginx配置
bash 复制代码
systemctl reload nginx
  • 查看Nginx服务状态
bash 复制代码
systemctl status nginx
bash 复制代码
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/local/nginx1.26.1/nginx.service; linked; vendor preset: disabled)
   Active: active (running) since 四 2025-09-25 15:01:04 CST; 2 months 21 days ago
     Docs: http://nginx.org/en/docs/
  Process: 68645 ExecStop=/usr/local/nginx1.26.1/sbin/nginx -s stop (code=exited, status=0/SUCCESS)
  Process: 1454 ExecReload=/usr/local/nginx1.26.1/sbin/nginx -s reload -c /usr/local/nginx1.26.1/conf/nginx.conf (code=exited, status=0/SUCCESS)
  Process: 68658 ExecStartPost=/bin/sleep 0.1 (code=exited, status=0/SUCCESS)
  Process: 68653 ExecStart=/usr/local/nginx1.26.1/sbin/nginx -c /usr/local/nginx1.26.1/conf/nginx.conf (code=exited, status=0/SUCCESS)
  Process: 68650 ExecStartPre=/usr/local/nginx1.26.1/sbin/nginx -t -c /usr/local/nginx1.26.1/conf/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 68654 (nginx)
    Tasks: 9
   Memory: 35.7M
   CGroup: /system.slice/nginx.service
           ├─68654 nginx: master process /usr/local/nginx1.26.1/sbin/nginx -c /usr/local/nginx1.26.1/conf/nginx.conf
           ├─68655 nginx: worker process
           ├─68656 nginx: worker process
           ├─68657 nginx: worker process
           ├─68659 nginx: worker process
           ├─68660 nginx: worker process
           ├─68661 nginx: worker process
           ├─68662 nginx: worker process
           └─68663 nginx: worker process

6. 正式启动OpenProject

重启OpenProject服务

  • 停止之前启动的测试服务
bash 复制代码
cd /public/application/openproject/
docker compose down
  • 使用.env中环境变量启动正式服务(支持域名,支持HTTPS)
bash 复制代码
cd /public/application/openproject/
docker compose up -d

访问正式OpenProject

7. 企业版功能

工具Github下载地址

部署工具

  1. 解压下载工具
bash 复制代码
unzip f5b2e55a2c2e3abb1f9eefcdf0bfff45-25f33dd28753c908455ac9e8969955795a865fb0.zip 
  1. 移动工具到程序目录
bash 复制代码
mv f5b2e55a2c2e3abb1f9eefcdf0bfff45-25f33dd28753c908455ac9e8969955795a865fb0 /public/application/openproject/openproject_crack
bash 复制代码
tree /public/application/openproject/openproject_crack/
# 显示结果
/public/application/openproject/openproject_crack/
└── enterprise_token.rb
  1. 赋权工具目录
  • 注意:如果之前已经存在运行服务(初始化过数据库),需要单独赋权工具目录。防止误修改数据库存储目录权限,导致OpenProject服务重启失败
bash 复制代码
sudo chown 1000:1000 -R /public/application/openproject/openproject_crack

修改docker-compose.yml

  1. 增加挂载工具的目录,"/public/application/openproject/openproject_crack/enterprise_token.rb:/app/app/models/enterprise_token.rb:ro"
bash 复制代码
x-op-restart-policy: &restart_policy
  restart: unless-stopped
x-op-image: &image
  image: openproject/openproject:${TAG:-16-slim}
x-op-app: &app
  <<: [*image, *restart_policy]
  environment:
    OPENPROJECT_HTTPS: "${OPENPROJECT_HTTPS:-true}"
    OPENPROJECT_HOST__NAME: "${OPENPROJECT_HOST__NAME:-localhost:8080}"
    OPENPROJECT_HSTS: "${OPENPROJECT_HSTS:-true}"
    RAILS_CACHE_STORE: "memcache"
    OPENPROJECT_CACHE__MEMCACHE__SERVER: "cache:11211"
    OPENPROJECT_RAILS__RELATIVE__URL__ROOT: "${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}"
    DATABASE_URL: "${DATABASE_URL:-postgres://postgres:p4ssw0rd@db/openproject?pool=20&encoding=unicode&reconnect=true}"
    RAILS_MIN_THREADS: ${RAILS_MIN_THREADS:-4}
    RAILS_MAX_THREADS: ${RAILS_MAX_THREADS:-16}
    # set to true to enable the email receiving feature. See ./docker/cron for more options
    IMAP_ENABLED: "${IMAP_ENABLED:-false}"
  volumes:
    - "${OPDATA:-opdata}:/var/openproject/assets"
    # 增加挂载工具的目录
    - "/public/application/openproject/openproject_crack/enterprise_token.rb:/app/app/models/enterprise_token.rb:ro"

重建OpenProject服务

  1. 停止服务
bash 复制代码
cd /public/application/openproject/
docker compose down
  1. 启动服务
bash 复制代码
cd /public/application/openproject/
docker compose up -d
  1. 查看服务许可

8. 备份与恢复功能

参见:OpenProject服务的备份与恢复

相关推荐
柏木乃一2 小时前
进程(2)进程概念与基本操作
linux·服务器·开发语言·性能优化·shell·进程
Lime-30902 小时前
制作Ubuntu 24.04-GPU服务器测试系统盘
linux·运维·ubuntu
代码or搬砖2 小时前
Nginx详讲
运维·nginx·dubbo
守城小轩2 小时前
基于Chrome140的Quora账号自动化——运行脚本(三)
运维·自动化·chrome devtools·指纹浏览器·浏览器开发
百年渔翁_肯肯2 小时前
Linux 与 Unix 的核心区别(清晰对比版)
linux·运维·unix
胡闹543 小时前
Linux查询防火墙放过的端口并额外增加需要通过的端口命令
linux·运维·windows
lc9991023 小时前
简洁高效的相机预览
android·linux
SongJX_4 小时前
DHCP服务
linux·运维·服务器
流形填表4 小时前
AI如何做SEO?
运维·人工智能·自动化·seo