Ubuntu 22.04 安装 Alf.io 2.0-M5-2609 指南

在 Ubuntu 22.04 服务器上从零安装开源票务系统 Alf.io 2.0-M5-2609 的完整指南,覆盖在线与离线两种方案、systemd 托管、Nginx HTTPS 反向代理、验证命令与常见问题排障。

Alf.ioAlf.io票务2026/10/23

Ubuntu 22.04 安装 Alf.io 2.0-M5-2609 指南

目标:在 Ubuntu 22.04 服务器上从零完成开源票务系统 Alf.io 2.0-M5-2609 的安装,包括 JDK 17 与 PostgreSQL 14 依赖、官方发布件部署、systemd 服务托管、Nginx HTTPS 反向代理、安装验证与卸载清理。本文提供「在线安装」与「离线安装」两种方案,全部命令与回显均在 Ubuntu 22.04.5 LTS(x86_64)实测通过。组件背景与选型对比见 《Alf.io 2.0-M5-2609 介绍与选型指南》。

一、环境信息

本章列出版文所依赖的实测环境,便于读者对照复现。

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Java 运行时:OpenJDK 17.0.20.1(openjdk-17-jre-headless,Alf.io 要求 Java 17)
  • 数据库:PostgreSQL 14.24-0ubuntu0.22.04.1(Alf.io 仅支持 PostgreSQL,10 及以上版本)
  • 反向代理:Nginx 1.18.0-6ubuntu14.21(负责 HTTPS 终结)
  • Alf.io 版本:2.0-M5-2609(官方发布件 alfio-2.0-M5-2609-boot.jar,约 79.5 MB / 83405439 字节)
  • 部署目录:/opt/alfio/
  • 运行账号:专用系统账号 alfio
  • 端口规划:应用本体 8080(本机回环)、PostgreSQL 5432(本机回环)、Nginx 对外 8443(HTTPS)
  • 示例域名:alfio.example.local(生产环境替换为你的真实域名)

二、前置条件

安装开始前需要确认服务器具备以下条件,每一项都给出验证命令与预期回显。

2.1 操作系统与权限

要求 root 或具备 sudo 权限的账号。确认系统版本:

cat /etc/os-release | grep PRETTY

实测输出:

PRETTY_NAME="Ubuntu 22.04.5 LTS"

2.2 网络与软件源

在线方案要求服务器能访问 Ubuntu 软件源与 GitHub。更新索引确认软件源可用:

apt-get update

实测输出(节选):

Get:7 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [1325 kB]
Get:8 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [4759 kB]
Fetched 12.5 MB in 4s (2866 kB/s)
Reading package lists...

⚠️ 注意:离线安装的服务器不要求外网连通,方案 B(第五章)会先在可联网环境把依赖下载为 deb 包,再拷贝到内网服务器安装。

2.3 硬件要求

官方 Getting Started 给出的最低要求:外置数据库部署 1 vCPU / 512MB 内存;数据库与应用同机部署 1 vCPU / 1GB 内存。本文按「应用与 PostgreSQL 同机」的最小可用形态实测,磁盘预留 2GB 以上(JAR 本体约 80MB,加数据库与日志余量)。

2.4 PostgreSQL 的必要性

Alf.io 是 Java 单体 Web 应用,唯一外部依赖是 PostgreSQL(不支持 MySQL/MariaDB)。应用启动时通过内置 Flyway 自动建表迁移,无需手工导入表结构。官方 README 同时要求:数据库账号不要使用超级用户(SUPERUSER),否则行级安全策略校验会被跳过——后文 4.5 节创建的 alfio 角色即普通角色。

三、版本选型说明

Alf.io 的版本号形如 2.0-M5-2609,含义是「2.0 第 5 个里程碑(M5)+ 构建年月(2609 = 2026 年 9 月)」。安装前先确认官方最新稳定版:

curl -s https://github.com/alfio-event/alf.io/releases.atom | grep -oE "<title>[^<]+</title>" | head -5

实测输出(查询日期 2026-10-23):

<title>Release 2.0-M5-2609</title>
<title>Release 2.0-M5-2606</title>
<title>Release 2.0-M5-2509-1</title>
<title>Release 2.0-M5-2509</title>

官方 Docker Hub 镜像 alfio/alf.io 的 latest 标签与 2.0-M5-2609 同日推送,两者指向同一构建。

关键差异与选型建议:2.0-M5-2609(2026-09-18 发布)是当前最新稳定版,为安全修复版,修复了扩展脚本相关的越权与 RCE 问题;若有存量部署停留在 2.0-M5-2509 或更早,建议直接升级到 2.0-M5-2609。本文全部步骤以 2.0-M5-2609 为准,安装其他版本只需替换下载 URL 与文件名中的版本号。

四、方案 A:在线安装(apt 依赖 + 官方发布件 JAR)

本章从零开始:安装 JDK 17、PostgreSQL 14、Nginx 三个依赖 → 下载官方 JAR → 建库建账号 → 写配置 → systemd 托管 → 首次启动拿管理员凭据 → 验证。全程约 10 分钟。

4.1 安装基础依赖

Alf.io 运行只需要 JRE(运行时环境),无需完整 JDK。一条命令装齐三个依赖:

apt-get install -y openjdk-17-jre-headless postgresql nginx

实测输出(节选,末尾阶段):

Setting up nginx (1.18.0-6ubuntu14.21) ...
Setting up postgresql-contrib (14+238) ...
Setting up postgresql (14+238) ...
Processing triggers for libc-bin (2.35-0ubuntu3.15) ...

安装完成后确认 Java 版本:

java -version

实测输出:

openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)

确认 PostgreSQL 服务已自启并监听本机回环:

systemctl is-active postgresql
ss -ltn | grep 5432

实测输出:

active
LISTEN 0      244        127.0.0.1:5432       0.0.0.0:*
LISTEN 0      244            [::1]:5432          [::]:*

💡 说明:PostgreSQL 14 默认只监听 127.0.0.1:5432,Alf.io 与数据库同机部署时无需放开外部监听,这是安全的默认值。

4.2 下载官方发布件

从 GitHub Releases 下载自包含的 Spring Boot 可执行 JAR,并计算 sha256 校验:

cd /tmp
wget https://github.com/alfio-event/alf.io/releases/download/2.0-M5-2609/alfio-2.0-M5-2609-boot.jar
sha256sum alfio-2.0-M5-2609-boot.jar

实测输出:

--2026-10-22 21:23:30--  https://github.com/alfio-event/alf.io/releases/download/2.0-M5-2609/alfio-2.0-M5-2609-boot.jar
Resolving github.com (github.com)... 20.205.243.166
Connecting to github.com (github.com)|20.205.243.166|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 83405439 (80M) [application/octet-stream]
Saving to: 'alfio-2.0-M5-2609-boot.jar'

alfio-2.0-M5-2609-bo 100%[===================>]  79.55M  12.7MB/s    in 6.3s

2026-10-22 21:23:37 (12.7 MB/s) - 'alfio-2.0-M5-2609-boot.jar' saved [83405439/83405439]

c769aa49fbd25ce8c348d78e4946b759dfa318bb7bffc0521378b78189176f39  alfio-2.0-M5-2609-boot.jar

💡 说明:83405439 字节与 c769aa49…76f39 校验值即 2.0-M5-2609 版本发布件指纹,下载后核对一致再继续。

4.3 部署目录与运行账号

按最小权限原则创建专用系统账号,部署目录归其所有:

useradd -r -m -d /opt/alfio -s /usr/sbin/nologin alfio
cp /tmp/alfio-2.0-M5-2609-boot.jar /opt/alfio/
chown -R alfio:alfio /opt/alfio
ls -la /opt/alfio/

实测输出:

total 81456
drwxr-xr-x 2 alfio alfio     4096 Oct 22 21:23 .
drwxr-xr-x 4 root  root      4096 Oct 22 21:23 ..
-rw-r--r-- 1 alfio alfio 83405439 Sep 18 07:02 alfio-2.0-M5-2609-boot.jar

4.4 初始化 PostgreSQL 数据库

创建普通角色 alfio(带密码)与同名数据库。密码用固定测试口令 q1w2e3r4,生产环境请换成强口令:

su postgres -c "psql -c \"CREATE ROLE alfio LOGIN PASSWORD 'q1w2e3r4';\""
su postgres -c "psql -c \"CREATE DATABASE alfio OWNER alfio;\""
su postgres -c "psql -c '\\du'"

实测输出:

CREATE ROLE
CREATE DATABASE
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 alfio     |                                                            | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

⚠️ 注意:CREATE ROLE 必须带 LOGIN PASSWORD。若创建时漏了密码,Alf.io 启动时会报 FATAL: password authentication failed for user "alfio"(排障见 8.1 节)。

4.5 外部配置文件

Alf.io 的外部配置文件放在 JAR 同目录的 application.properties,Spring Boot 启动时自动读取。写入数据库连接与基础安全项:

cat > /opt/alfio/application.properties <<'EOF'
# Alf.io external configuration
datasource.url=jdbc:postgresql://localhost:5432/alfio
datasource.username=alfio
datasource.password=q1w2e3r4
alfio.base-url=https://alfio.example.local
server.forward-headers-strategy=native
server.servlet.session.cookie.http-only=true
server.servlet.session.timeout=2h
server.compression.enabled=true
server.shutdown=graceful
spring.application.name=Alf.io
logging.level.root=warn
logging.level.alfio=info
EOF
chown alfio:alfio /opt/alfio/application.properties

逐项说明:

配置项取值说明
datasource.urljdbc:postgresql://localhost:5432/alfio数据库 JDBC 连接串,指向 4.4 节创建的库
datasource.username / datasource.passwordalfio / q1w2e3r4数据库账号密码,与 4.4 节一致
alfio.base-urlhttps://alfio.example.local应用对外基础 URL,用于邮件链接与跳转
server.forward-headers-strategynative让应用信任反向代理传来的 X-Forwarded-* 头
server.servlet.session.cookie.http-onlytrue会话 Cookie 禁止 JS 读取
server.servlet.session.timeout2h会话有效期
server.compression.enabledtrueHTTP 响应压缩
server.shutdowngraceful优雅停机,systemd 停止时不丢请求
logging.level.root / logging.level.alfiowarn / info日志级别:框架告警级,业务信息级

⚠️ 注意:alfio.base-url 属性只影响应用内部生成的链接;管理后台的「Base URL」配置键(BASE_URL)需要在首次登录后的基础设置向导中填写(见 7.4 节),两者建议保持一致。实测中未配置后台 BASE_URL 键时,通过 API 创建活动会失败(见 8.4 节)。

4.6 systemd 托管

创建服务单元,JVM 堆内存显式限制在 256–512MB(本文选择 -Xms256m -Xmx512m):

cat > /etc/systemd/system/alfio.service <<'EOF'
[Unit]
Description=Alf.io ticket reservation system
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=alfio
WorkingDirectory=/opt/alfio
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /opt/alfio/alfio-2.0-M5-2609-boot.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable alfio
systemctl start alfio
systemctl is-active alfio

实测输出:

Created symlink /etc/systemd/system/multi-user.target.wants/alfio.service → /etc/systemd/system/alfio.service.
active

单元文件逐项说明:

配置项取值说明
After / Wants=postgresql.service—保证数据库先于应用启动
User=alfio—以非特权账号运行
WorkingDirectory=/opt/alfio—使 Spring Boot 读取该目录下的 application.properties
ExecStart 的 -Xms256m -Xmx512m—初始堆 256MB、最大堆 512MB,符合官方最低内存要求
SuccessExitStatus=143—SIGTERM 正常退出码,避免优雅停机被记为失败
Restart=on-failure / RestartSec=10—异常退出 10 秒后自动拉起

4.7 首次启动与管理员凭据

Alf.io 首次启动时自动建表、初始化,并随机生成管理员账号 admin 的初始密码,打印在服务日志里。查看:

journalctl -u alfio --no-pager | grep -A 2 "generated admin credentials"

实测输出:

Oct 22 21:24:04 alfio-b1 java[6729]: 2026-10-22T21:24:04.798Z  INFO 6729 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           :    here the generated admin credentials:
Oct 22 21:24:04 alfio-b1 java[6729]: 2026-10-22T21:24:04.808Z  INFO 6729 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           : initialized alf.io version 2.0-M5-2609
Oct 22 21:24:04 alfio-b1 java[6729]: 2026-10-22T21:24:04.809Z  INFO 6729 --- [Alf.io] [           main] a.c.SpringBootLauncher                   : Started SpringBootLauncher in 4.532 seconds (process running for 5.092)

generated admin credentials: 下一行即为随机初始密码(本例为 5qS&ZoSjXsApI3b%&mN)。立即记录该密码并登录后台修改;忘记且未修改过时,可按 8.2 节重新生成。启动耗时约 5 秒(Started SpringBootLauncher in 4.532 seconds)。

4.8 安装验证

依次确认进程、监听端口与 HTTP 响应:

ps -ef | grep [a]lfio
ss -ltn | grep 8080
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://localhost:8080/

实测输出:

alfio       9045       1  0 00:39 ?        00:00:47 /usr/bin/java -Xms256m -Xmx512m -jar /opt/alfio/alfio-2.0-M5-2609-boot.jar
LISTEN 0      50                 *:8080             *:*
302 -> https://localhost:8443/

💡 说明:应用主进程由 systemd 以 alfio 账号运行,堆参数 -Xms256m -Xmx512m 生效;http://localhost:8080/ 返回 302 跳转到 alfio.base-url 指向的对外地址,说明基础 URL 已生效(详见 8.5 节)。

管理后台登录验证(Nginx 配好后也可直接对 8443 做):

curl -sk -o /dev/null -w "%{http_code} %{redirect_url}\n" https://localhost:8443/admin/
curl -sk https://localhost:8443/admin/ | grep -oE "<title>[^<]+</title>"

实测输出:

302 https://localhost:8443/authentication
<title>Alf.io Admin</title>

未登录访问 /admin/ 会 302 到登录页 /authentication,登录页标题为 Alf.io Admin,说明 Web 后台正常。

五、方案 B:离线安装(deb 离线包 + 离线 JAR)

内网隔离环境无法访问 Ubuntu 源与 GitHub。方案 B 在可联网的同版本环境预先下载全部 deb 依赖与 JAR,打包拷入内网后离线安装。实测在全新 Ubuntu 22.04 环境完整走通。

5.1 制作离线依赖包(联网环境执行)

在目标系统同版本(Ubuntu 22.04)的联网环境中,用 apt-get download 把 openjdk-17-jre-headless、postgresql、nginx 及其全部递归依赖下载为 deb 文件:

mkdir -p /opt/alfio-debs && cd /opt/alfio-debs
apt-get update
apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests \
  --no-conflicts --no-breaks --no-replaces --no-enhances \
  openjdk-17-jre-headless postgresql nginx | grep "^\w" | sort -u)
du -sh /opt/alfio-debs
ls /opt/alfio-debs | wc -l

实测输出(节选):

Get:90 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 postgresql-14 amd64 14.24-0ubuntu0.22.04.1 [16.3 MB]
Get:91 http://archive.ubuntu.com/ubuntu jammy/main amd64 postgresql all 14+238 [3288 B]
Get:92 http://archive.ubuntu.com/ubuntu jammy/main amd64 postgresql-contrib all 14+238 [3292 B]
Download complete and in download only mode
110M    /opt/alfio-debs
95

共 95 个 deb 文件、约 110MB。连同 JAR 一起打包:

cp /tmp/alfio-2.0-M5-2609-boot.jar /opt/alfio-debs/
tar -czf alfio-2.0-M5-2609-offline.tar.gz -C /opt alfio-debs

把 alfio-2.0-M5-2609-offline.tar.gz 通过内网介质(U 盘/内网文件服务)拷贝到目标服务器。

5.2 离线安装依赖(目标服务器执行)

解包并用 dpkg 批量安装全部 deb:

tar -xzf alfio-2.0-M5-2609-offline.tar.gz -C /opt
dpkg -i /opt/alfio-debs/*.deb

实测输出(节选):

Setting up nginx-common (1.18.0-6ubuntu14.21) ...
Setting up postgresql-14 (14.24-0ubuntu0.22.04.1) ...
Setting up nginx-core (1.18.0-6ubuntu14.21) ...
Setting up nginx (1.18.0-6ubuntu14.21) ...
Setting up openjdk-17-jre-headless:amd64 (17.0.20.1+1-1~22.04) ...

安装结果与依赖补齐情况:

java -version
systemctl is-enabled postgresql
systemctl is-active postgresql

实测输出:

openjdk version "17.0.20.1" 2026-08-18
enabled
active

💡 说明:dpkg -i 不解析网络依赖,95 个包内已包含全部递归依赖,顺序由 dpkg 自行排序;个别包提示依赖未满足时,对同一目录重跑一次 dpkg -i /opt/alfio-debs/*.deb 即可。

5.3 部署 Alf.io 与初始化数据库

与方案 A 相同:建账号、放 JAR、写配置、建库(离线 JAR 已在 /opt/alfio-debs/ 内):

useradd -r -m -d /opt/alfio -s /usr/sbin/nologin alfio
cp /opt/alfio-debs/alfio-2.0-M5-2609-boot.jar /opt/alfio/
chown -R alfio:alfio /opt/alfio
cat > /opt/alfio/application.properties <<'EOF'
# Alf.io external configuration
datasource.url=jdbc:postgresql://localhost:5432/alfio
datasource.username=alfio
datasource.password=q1w2e3r4
alfio.base-url=https://alfio.example.local
server.forward-headers-strategy=native
server.servlet.session.cookie.http-only=true
server.servlet.session.timeout=2h
server.compression.enabled=true
server.shutdown=graceful
spring.application.name=Alf.io
logging.level.root=warn
logging.level.alfio=info
EOF
chown alfio:alfio /opt/alfio/application.properties
su postgres -c "psql -c \"CREATE ROLE alfio LOGIN PASSWORD 'q1w2e3r4';\""
su postgres -c "psql -c \"CREATE DATABASE alfio OWNER alfio;\""

实测输出:

CREATE ROLE
CREATE DATABASE

5.4 systemd 托管与验证

创建与 4.6 节完全相同的服务单元并启动:

cat > /etc/systemd/system/alfio.service <<'EOF'
[Unit]
Description=Alf.io ticket reservation system
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=alfio
WorkingDirectory=/opt/alfio
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /opt/alfio/alfio-2.0-M5-2609-boot.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable alfio
systemctl start alfio
systemctl is-active alfio
journalctl -u alfio --no-pager | grep -A 2 "generated admin credentials"

实测输出:

Created symlink /etc/systemd/system/multi-user.target.wants/alfio.service → /etc/systemd/system/alfio.service.
active
Oct 22 21:30:27 alfio-offline java[6251]: 2026-10-22T21:30:27.346Z  INFO 6251 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           : initialized alf.io version 2.0-M5-2609
Oct 22 21:30:27 alfio-offline java[6251]: 2026-10-22T21:30:27.348Z  INFO 6251 --- [Alf.io] [           main] a.c.SpringBootLauncher                   : Started SpringBootLauncher in 5.02 seconds (process running for 5.627)

generated admin credentials: 下一行即本次随机生成的初始密码(本例为 W7~dxqq5ZMPadMV=)St2)。端口验证:

ss -ltn | grep 8080

实测输出:

LISTEN 0      50                 *:8080             *:*

离线方案到此完成,后续 Nginx 反向代理(7.1 节)与方案 A 完全一致。Nginx 已随 deb 包装好,无需再联网。

六、方案对比与选择建议

两种方案的差异汇总如下:

维度方案 A:在线安装方案 B:离线安装
依赖获取apt-get install 实时拉取预先 apt-get download 95 个 deb(约 110MB)
是否需外网安装机需访问 Ubuntu 源 + GitHub仅制作离线包的机器需外网,安装机全程离线
JAR 获取wget 官方 Releases 直链随离线包拷入
systemd 服务名alfio.service(自建单元)同左
应用监听端口80808080
版本一致性由软件源当时状态决定离线包制作时锁定
适用场景可联网的云主机、办公服务器内网隔离、合规审计要求锁定版本的环境

选择建议:服务器可直接访问公网选方案 A,步骤最少且始终拿到最新依赖;内网隔离或需要版本锁定选方案 B,离线包与在线方案装出的组件版本完全一致(均为 PostgreSQL 14.24 / Nginx 1.18.0 / OpenJDK 17.0.20.1)。

七、配置说明

本章覆盖两种方案共用的对外发布(Nginx HTTPS)、JVM 内存、端口与 BASE_URL 配置。

7.1 Nginx 反向代理与 HTTPS

Alf.io 内嵌 Jetty 直接服务 HTTP,生产环境建议由 Nginx 终结 HTTPS 再反代到 8080。先生成自签名证书(已有正式证书可跳过生成步骤直接改路径):

mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 \
  -keyout /etc/nginx/ssl/alfio.key -out /etc/nginx/ssl/alfio.crt \
  -subj "/CN=alfio.example.local"

实测输出为密钥生成的随机字符进度点(节选首尾):

..+..........+..+......+.......+..+.+.....+.......+...+.....+.+.....+......+...+.......+............+...+...+......+.........+.....+.+......
...(中间省略随机字符点)...
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----

写入反代配置:

cat > /etc/nginx/sites-available/alfio <<'EOF'
server {
    listen 8443 ssl;
    server_name alfio.example.local;

    ssl_certificate     /etc/nginx/ssl/alfio.crt;
    ssl_certificate_key /etc/nginx/ssl/alfio.key;
    ssl_protocols       TLSv1.2 TLSv1.3;

    location / {
        proxy_pass         http://127.0.0.1:8080;
        proxy_set_header   Host              $host;
        proxy_set_header   X-Forwarded-Proto https;
        proxy_set_header   X-Forwarded-Host  $host:8443;
        proxy_set_header   X-Forwarded-Port  8443;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    }
}
EOF
ln -sf /etc/nginx/sites-available/alfio /etc/nginx/sites-enabled/alfio
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl enable nginx
systemctl restart nginx
ss -ltn | grep 8443

实测输出:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
LISTEN 0      511          0.0.0.0:8443       0.0.0.0:*

配置逐项说明:

配置项取值说明
listen 8443 ssl—对外 HTTPS 端口;用 8443 而非 443 是本例为避免与已有站点冲突,无冲突可改 443
ssl_protocolsTLSv1.2 TLSv1.3禁用不安全的旧协议
proxy_passhttp://127.0.0.1:8080转发到本机 Alf.io
X-Forwarded-Proto/Host/Port—配合应用的 server.forward-headers-strategy=native,让应用生成正确的对外链接
rm -f sites-enabled/default—移除默认站点,避免抢占 80 端口

登录链路验证(未登录 → 登录页):

curl -sk -o /dev/null -w "%{http_code} %{redirect_url}\n" https://localhost:8443/admin/
curl -sk -o /dev/null -w "%{http_code}\n" https://localhost:8443/authentication

实测输出:

302 https://localhost:8443/authentication
200

7.2 JVM 堆内存调整

堆内存由 systemd 单元的 ExecStart 行控制(4.6 节)。修改后需重载并重启:

sed -i 's/-Xms256m -Xmx512m/-Xms256m -Xmx512m/' /etc/systemd/system/alfio.service
systemctl daemon-reload
systemctl restart alfio

确认实际生效的堆参数:

ps -ef | grep [a]lfio

实测输出:

alfio       9045       1  0 00:39 ?        00:00:47 /usr/bin/java -Xms256m -Xmx512m -jar /opt/alfio/alfio-2.0-M5-2609-boot.jar

若安装了完整 JDK(而非 JRE),还可用 jcmd 查看运行时堆确认:

jcmd $(pgrep -f 'alfio-2.0-M5-2609-boot.jar') VM.flags | grep -oE "(Initial|Max)HeapSize=[0-9]+"

实测输出(256MB = 268435456,512MB = 536870912):

-XX:InitialHeapSize=268435456
-XX:MaxHeapSize=536870912

💡 说明:-Xms256m -Xmx512m 满足官方最低内存要求(同机部署数据库 1GB 内存起)。活动规模大、并发高时可按 1GB/2GB 上调 -Xmx,同时等比上调服务器内存。

7.3 监听端口调整

应用默认监听 8080。临时换端口可用环境变量 SERVER_PORT 覆盖:

systemctl stop alfio
su alfio -s /bin/bash -c "cd /opt/alfio && SERVER_PORT=8096 java -Xms256m -Xmx512m -jar alfio-2.0-M5-2609-boot.jar &"
sleep 15
ss -ltn | grep 8096

实测输出:

LISTEN 0      50                 *:8096             *:*

验证后停掉手工进程,恢复 systemd 托管:

pkill -f 'SERVER_PORT=8096' ; systemctl start alfio ; systemctl is-active alfio

实测输出:

active

⚠️ 注意:环境变量只对当次进程生效,长期改端口应在 /opt/alfio/application.properties 中加 server.port=8096 后重启服务,不要依赖手工环境变量。

7.4 BASE_URL 与首次基础配置

首次用浏览器打开 https://alfio.example.local:8443/admin/,用 4.7 节记录的初始密码登录,系统会弹出「基础设置」向导(官方文档称 Required options),需要完成:

  1. 支持语言(Supported languages):勾选前台需要的语言,默认含英文;
  2. Base URL:填对外访问地址,本例 https://alfio.example.local,与 alfio.base-url 属性保持一致;
  3. 邮件与地图:可后续再配,向导允许只填必填项。

该向导落库的是系统级 BASE_URL 配置键。实测中,未完成该向导(BASE_URL 为空)时活动创建会被阻断,报 Mandatory configuration key BASE_URL not present(排障与命令行修复见 8.4 节;配置体系全解见《Alf.io 2.0-M5-2609 配置参数详解》)。

数据库层面的备份建议:系统级配置与业务数据都在 PostgreSQL alfio 库内,定期导出即可整体备份:

su postgres -c "pg_dump alfio | gzip > /var/backups/alfio-$(date +%F).sql.gz"
ls -la /var/backups/ | grep alfio

实测输出:

-rw-r--r-- 1 root root 39561 Oct 22 21:26 /var/backups/alfio-2026-10-23.sql.gz

恢复:gunzip -c /var/backups/alfio-2026-10-23.sql.gz | su postgres -c "psql alfio"。

八、常见问题(FAQ)

本章收录实测安装过程中真实出现过的问题,均给出「现象 → 定位 → 解决」。

Q1:启动即失败,日志报 FATAL: password authentication failed for user "alfio",如何解决?

数据库角色的密码与 datasource.password 不匹配。定位方法:

journalctl -u alfio --no-pager | grep -E "PSQLException|Application run failed" | tail -2

实测输出:

Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "alfio"
2026-10-22T21:26:58.370Z ERROR 7626 --- [Alf.io] [           main] o.s.b.SpringApplication                  : Application run failed
Caused by: org.postgresql.util.PSQLException: FATAL: password authentication failed for user "alfio"

解决:补设角色密码后重启服务:

su postgres -c "psql -c \"ALTER USER alfio WITH PASSWORD 'q1w2e3r4';\""
systemctl restart alfio
systemctl is-active alfio
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/

实测输出:

ALTER ROLE
active
302

Q2:管理员初始密码弄丢了,又还没登录后台改过,怎么办?

Alf.io 只在「首次初始化」时生成管理员凭据。删除初始化标记与管理员账号,重启后即重新走一遍初始化并生成新密码。先备份数据库(7.4 节命令),再执行:

su postgres -c "psql alfio -c \"DELETE FROM configuration WHERE c_key='INIT_COMPLETED';\""
su postgres -c "psql alfio -c \"DELETE FROM ba_user WHERE username='admin';\""
su postgres -c "psql alfio -c \"DELETE FROM authority WHERE username='admin';\""
systemctl restart alfio
journalctl -u alfio --no-pager | grep -A 2 "generated admin credentials"

实测输出:

DELETE 0
DELETE 1
DELETE 1
active
Oct 23 00:37:05 alfio-b1 java[8798]: 2026-10-23T00:37:05.654Z  INFO 8798 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           :    This is the first time you're running alf.io
Oct 23 00:37:05 alfio-b1 java[8798]: 2026-10-23T00:37:05.654Z  INFO 8798 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           :    here the generated admin credentials:
Oct 23 00:37:05 alfio-b1 java[8798]: 2026-10-23T00:37:05.655Z  INFO 8798 --- [Alf.io] [           main] a.c.ConfigurationStatusChecker           :    NNtHfOzVERRyVRB6j

⚠️ 注意:三张表都要删。实测只删 INIT_COMPLETED 而不删 ba_user 里的 admin 行时,重启会因重复键插入失败,服务起不来:

2026-10-23T00:36:44.569Z  WARN 8656 --- [Alf.io] [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.dao.DuplicateKeyException: ...ERROR: duplicate key value violates unique constraint "unique_username"
Oct 23 00:36:44 alfio-b1 java[8656]:   Detail: Key (username)=(admin) already exists.

此时把 ba_user、authority 中的 admin 行一并删除(Q2 步骤)再重启即可恢复。

Q3:systemctl mask alfio 报 Failed to mask unit: File /etc/systemd/system/alfio.service already exists.?

mask 的语义是把单元软链到 /dev/null,因此要求原单元文件先移走:

mv /etc/systemd/system/alfio.service /root/alfio.service.bak
systemctl mask alfio
systemctl start alfio
systemctl is-active alfio

实测输出:

Created symlink /etc/systemd/system/alfio.service → /dev/null.
Failed to start alfio.service: Unit alfio.service is masked.
masked

恢复 unmask 并放回文件:

systemctl unmask alfio
mv /root/alfio.service.bak /etc/systemd/system/alfio.service
systemctl daemon-reload
systemctl enable alfio
systemctl start alfio
systemctl is-active alfio

实测输出:

Removed /etc/systemd/system/alfio.service.
Removed /etc/systemd/system/multi-user.target.wants/alfio.service.
Created symlink /etc/systemd/system/multi-user.target.wants/alfio.service → /etc/systemd/system/alfio.service.
enabled
active

Q4:通过 API 创建活动报 Mandatory configuration key BASE_URL not present(500),怎么修?

这是管理后台的「Base URL」配置键未设置(7.4 节向导未完成)。应用日志可见根因:

java.lang.IllegalArgumentException: Mandatory configuration key BASE_URL not present
        at alfio.manager.system.ConfigurationManager$MaybeConfiguration.getRequiredValue(ConfigurationManager.java:788) ~[!/:2.0-M5-2609]

修复方式一(推荐):登录管理后台完成基础设置向导。修复方式二(命令行,管理员会话):登录后台页面取 CSRF 令牌后调用配置接口:

# 1) 表单登录拿会话(用户名 admin、密码为首次启动生成的初始密码)
curl -sk -c /tmp/alf-cj.txt -o /tmp/alf-login.html https://localhost:8443/authentication
CSRF=$(grep -oE "name=\"_csrf\" type=\"hidden\" value=\"[^\"]+\"" /tmp/alf-login.html | sed -E "s/.*value=\"([^\"]+)\".*/\1/")
curl -sk -b /tmp/alf-cj.txt -c /tmp/alf-cj.txt -o /dev/null -w "login=%{http_code}\n" \
  -d "username=admin" -d "password=NNtHfOzVERRyVRB6j" -d "_csrf=$CSRF" \
  https://localhost:8443/authenticate
# 2) 从后台页面元数据取 CSRF 令牌
CSRF=$(curl -sk -b /tmp/alf-cj.txt https://localhost:8443/admin/ | grep -oE "<meta name=\"_csrf\" content=\"[^\"]+\"" | sed -E "s/.*content=\"([^\"]+)\".*/\1/")
# 3) 写入系统级 BASE_URL
curl -sk -b /tmp/alf-cj.txt -X POST -H "X-CSRF-TOKEN: $CSRF" -H "Content-Type: application/json" \
  -w "\n[%{http_code}]\n" \
  -d "{\"GENERAL\":[{\"key\":\"BASE_URL\",\"value\":\"https://alfio.example.local\"}]}" \
  https://localhost:8443/admin/api/configuration/update-bulk

实测输出:

login=302
true
[200]

复核落库结果:

curl -sk -b /tmp/alf-cj.txt https://localhost:8443/admin/api/configuration/load \
  | grep -oE '"key": "BASE_URL"[^}]*"value": "[^"]*"'

实测输出:

"key": "BASE_URL", "value": null ... → 修复后 "key": "BASE_URL" ... "value": "https://alfio.example.local"

Q5:直接访问 http://服务器IP:8080/ 为什么 302 跳到了别的地址?

应用会把根路径重定向到配置的对外基础 URL(属性 alfio.base-url),这是预期行为而非故障:

curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://localhost:8080/

实测输出:

302 -> https://localhost:8443/

生产环境把 alfio.base-url 与后台 BASE_URL 都设为用户实际访问的域名(含端口),避免出现「跳到一个打不开的地址」。

Q6:想临时起一个免配置的开发实例验证功能,怎么做?

Alf.io 提供 dev 运行档案,用于本地开发调试:

cd /opt/alfio
java -jar alfio-2.0-M5-2609-boot.jar --spring.profiles.active=dev

实测输出(节选):

a.c.SpringBootLauncher                   : Started SpringBootLauncher in 3.319 seconds (process running for 3.85)
a.c.SpringBootLauncher                   : profiles: requested , active spring-boot, dev

dev 档案下应用监听 8099(与生产 8080 不同,避免端口冲突):

http 8099 /admin/: 302 -> http://localhost:8099/authentication

⚠️ 注意:dev 档案面向本地调试,不得用于生产;生产一律按第四/五章的 systemd 方式运行。

九、卸载与清理

完全卸载 Alf.io 及其依赖(数据库数据会一并删除,操作前务必确认已有备份):

systemctl disable --now alfio
rm -f /etc/systemd/system/alfio.service
systemctl daemon-reload
rm -rf /opt/alfio
apt-get purge -y postgresql postgresql-contrib nginx nginx-common openjdk-17-jre-headless
rm -f /etc/nginx/sites-enabled/alfio /etc/nginx/sites-available/alfio
rm -rf /etc/nginx/ssl
userdel alfio

实测输出(节选):

Dropping cluster main...
Purging configuration files for openjdk-17-jre-headless:amd64 (17.0.20.1+1-1~22.04) ...
Reading state information...
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.

确认 Java 已移除(残留的只读目录属正常,update-alternatives 已无 java 项):

java -version

实测输出:

-bash: /usr/bin/java: No such file or directory

如需彻底清掉数据库数据目录:rm -rf /var/lib/postgresql(确认备份在手后再执行)。

十、参考链接