Ubuntu 24.04 安装 GoatCounter 2.7.0 指南

Ubuntu 24.04 安装 GoatCounter 2.7.0 指南:官方预编译二进制与源码编译两种方案全流程实测,含 sha256 校验、建站初始化、systemd 托管与验证回显、FAQ 与卸载清理。

GoatCounter自托管GoSQLite监控LinuxGoatCounter2026/10/30

Ubuntu 24.04 安装 GoatCounter 2.7.0 指南

目标:在一台全新 Ubuntu 24.04 LTS 服务器上,把 GoatCounter 2.7.0 装成 systemd 托管的常驻服务,并跑通首条页面访问数据。全文提供两种安装方案——方案 A 官方预编译二进制(推荐)、方案 B 源码编译——所有命令与回显均在 Ubuntu 24.04.5 LTS 实测通过(实测日期:2026-10-29),可逐条照做复现。

一、环境信息

实测服务器基线(回显照抄):

$ uname -a
Linux 9e73505334fa 7.0.0-38-generic #38-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep  4 09:10:14 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
$ grep PRETTY /etc/os-release
PRETTY_NAME="Ubuntu 24.04.5 LTS"
$ free -h | head -2
               total        used        free      shared  buff/cache   available
Mem:            15Gi       7.7Gi       2.5Gi       221Mi       5.4Gi       7.4Gi
$ df -h --output=size,used,avail,pcent,target /
  Size  Used Avail Use% Mounted on
  295G  127G  153G  46% /
项目值说明
操作系统Ubuntu 24.04.5 LTS同样适用于 22.04/20.04,命令无差异
内核7.0.0-38-genericx86_64
CPU / 内存 / 磁盘6 核 / 15 GiB / 295 GB远超最低要求,见 2.1
GoatCounterv2.7.0官方最新稳定版(2026-10-29 核验 GitHub Releases)
Go 工具链(仅方案 B)go1.25.5与官方二进制编译版本一致
编译器(仅方案 B)gcc 13.3.0cgo 编译 SQLite 驱动所需
实测端口8135可按需更换

二、前置条件

2.1 硬件与系统要求

GoatCounter 是单二进制 Go 程序,对硬件要求极低:

  • 内存:实测服务进程常驻 32.8MB(峰值 98.9MB,systemctl status 回显),128MB 以上内存的设备即可承载中小流量;
  • 磁盘:二进制本身约 28MB,SQLite 数据库随流量增长(实测初始化后约 0.5MB);
  • 架构:官方为 linux-amd64 / linux-arm64 等发行预编译二进制( Releases 资产列表),ARM 服务器直接选对应资产即可,无需交叉编译。

2.2 软件依赖

方案 A 只用到系统自带工具:wget(或 curl)、tar/gzip、sha256sum、systemd(Ubuntu 24.04 默认具备),SQLite 已编译进二进制、无外部数据库依赖。

方案 B 额外需要 Go 工具链(≥ go.mod 声明的版本,本文用 1.25.5)与 C 编译器(gcc + libc 头文件,见 5.3)。

2.3 端口与网络规划

  • 8135/tcp:GoatCounter 自身监听端口(本文实测值,任意未占用端口均可);
  • 80/443:若用 -tls acme 自动证书或前置 nginx/Caddy 反代时开放;
  • 出网:安装期需要访问 GitHub Releases(下载二进制/源码);方案 B 还需访问 Go 模块代理。

2.4 账号与目录规划

路径/账号用途
/usr/local/bin/goatcounter主程序(两个方案最终产物相同)
/var/lib/goatcounter/数据目录(SQLite 数据库文件所在,属主 goatcounter)
系统用户 goatcounter服务运行身份(无登录 shell 的系统用户)
/etc/systemd/system/goatcounter.servicesystemd 服务单元

2.5 官方发行物形态

GoatCounter 不提供 apt/yum 软件仓库,也没有 deb/rpm 包,官方分发形态只有两种(GitHub Releases 页,2026-10-29 核验):

  1. 压缩的单文件二进制,如 goatcounter-v2.7.0-linux-amd64.gz(gzip 压缩、非 tar 包,解压即得可执行文件);
  2. 源码归档 v2.7.0.tar.gz(即 5.4 使用的源码包)。

因此安装方案相应只有「官方二进制」与「源码编译」两种,本文各成一章。

三、版本选型说明

  • 选定版本:v2.7.0,2026-10-29 经 GitHub Releases 页与版本徽章双重核验为最新稳定 tag,本系列其余三篇(介绍选型 / 配置详解 / CLI 命令)均在同版本实测,全文命令与回显可对齐复现。
  • linux-amd64 发行资产:goatcounter-v2.7.0-linux-amd64.gz,实测 13,935,060 字节(约 13.3MB);sha256 实测值见 4.2。
  • 版本内嵌信息:官方二进制 version 子命令输出 version=v2.7.0; go=go1.25.5; GOOS=linux; GOARCH=amd64; race=false; cgo=true——cgo=true 说明 SQLite 驱动以 C 编译嵌入,这也是方案 B 需要 gcc 的原因。
  • 升级路径:GoatCounter 无守护进程常驻状态、数据在单文件库中,升级=替换二进制 + systemctl restart(新版本会提示执行 goatcounter db migrate all 完成库结构迁移,详见站内 CLI 命令篇)。

四、方案 A:官方预编译二进制安装(推荐)

4.1 方案说明

直接使用官方在 GitHub Releases 发布的预编译二进制:静态链接、SQLite/PostgreSQL 驱动与全部模板静态资源已编译内嵌,解压即用,无需任何编译环境。适合绝大多数生产场景,也是官方 README 的标准路径。

4.2 下载与完整性校验

cd /tmp
# 下载发行包(13,935,060 字节)
wget https://github.com/arp242/goatcounter/releases/download/v2.7.0/goatcounter-v2.7.0-linux-amd64.gz
# 校验完整性(实测值,与官方 .sha256 发布值核对一致)
sha256sum goatcounter-v2.7.0-linux-amd64.gz
# 98d221cb9c8ef2bf76d8daa9cca647839f8d8b0bb5bc7400ff9337c5da834511  goatcounter-v2.7.0-linux-amd64.gz
gzip -t goatcounter-v2.7.0-linux-amd64.gz   # 解压完整性检查,无输出即正常

💡 离线服务器场景:在有外网的机器完成上述下载与校验后,把 goatcounter-v2.7.0-linux-amd64.gz 单文件拷贝(U 盘/内网 scp 均可)到目标服务器,重跑 sha256sum 比对一致即可继续 4.3。整个方案 A 不需要目标服务器出网。

4.3 安装二进制

cd /tmp
gunzip goatcounter-v2.7.0-linux-amd64.gz            # 解压得 goatcounter-v2.7.0-linux-amd64
install -m 0755 goatcounter-v2.7.0-linux-amd64 /usr/local/bin/goatcounter
/usr/local/bin/goatcounter version

实测回显:

version=v2.7.0; go=go1.25.5; GOOS=linux; GOARCH=amd64; race=false; cgo=true

安装后的文件属性(实测):大小 29,273,880 字节;ldd /usr/local/bin/goatcounter 返回 not a dynamic executable(静态链接,无 so 依赖)。

4.4 创建运行用户与数据目录

useradd -r -d /var/lib/goatcounter -s /usr/sbin/nologin goatcounter
mkdir -p /var/lib/goatcounter
chown goatcounter:goatcounter /var/lib/goatcounter

4.5 初始化站点与管理员

GoatCounter 以「站点(site)」为单位组织数据,一个站点对应一个 vhost 域名;首次初始化即创建库文件、默认站点与管理员账号:

goatcounter db create site \
  -db 'sqlite+/var/lib/goatcounter/db.sqlite3' \
  -vhost stats.example.com \
  -user.email admin@example.com \
  -user.password 'q1w2e3r4' \
  -createdb

实测回显:命令成功时无任何输出直接退出(exit 0),-createdb 自动创建了 507,904 字节的库文件。用 db query 确认落库(实测回显):

$ goatcounter db query -db 'sqlite+/var/lib/goatcounter/db.sqlite3' \
    "select site_id, cname, created_at from sites;"
site_id  cname              created_at
1        stats.example.com  2026-10-29 14:17:39

两点说明(均为实测结论):

  • -user.password 可省略,此时交互式提示 Enter password for new user (will not echo);在无终端的脚本环境会报 goatcounter: getTermios: inappropriate ioctl for device 并失败,自动化脚本务必显式传参。
  • -createdb 仅在库文件不存在时需要;对已存在的库重复加 -createdb 会拒绝执行,防止误建。

4.6 编写 systemd 服务单元

/etc/systemd/system/goatcounter.service(完整原文,实测可用):

[Unit]
Description=GoatCounter web analytics server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=goatcounter
Group=goatcounter
WorkingDirectory=/var/lib/goatcounter
ExecStart=/usr/local/bin/goatcounter serve -listen :8135 -public-port 8135 -db sqlite+/var/lib/goatcounter/db.sqlite3
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

ExecStart 中三个旗标的含义:-listen :8135 实际监听地址;-public-port 8135 对外公布的端口(置于反向代理之后、对外端口不同时改为代理端口);-db sqlite+<文件> 存储连接串(PostgreSQL 写法与更多旗标见站内配置详解篇)。

4.7 启动、自启与验证

systemctl daemon-reload
systemctl enable --now goatcounter

systemctl status goatcounter 实测回显(节选):

● goatcounter.service - GoatCounter web analytics server
     Loaded: loaded (/etc/systemd/system/goatcounter.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-10-29 14:23:49 UTC; 29min ago
   Main PID: 1036 (goatcounter)
      Tasks: 12 (limit: 2266)
     Memory: 32.8M (peak: 98.9M)
        CPU: 2.746s

systemctl is-enabled goatcounter → enabled;systemctl is-active goatcounter → active。首次启动日志(journalctl -u goatcounter 实测):

Oct 29 14:17:50 9e73505334fa systemd[1]: Started goatcounter.service - GoatCounter web analytics server.
Oct 29 14:17:50 9e73505334fa goatcounter[264]: Oct 29 14:17:50  INFO  startup: GoatCounter ready
Oct 29 14:17:50 9e73505334fa goatcounter[264]:                         num_sites         = 1
Oct 29 14:17:50 9e73505334fa goatcounter[264]:                         sites             = [stats.example.com]
Oct 29 14:17:50 9e73505334fa goatcounter[264]:                         listen            = :8135
Oct 29 14:17:50 9e73505334fa goatcounter[264]:                         dev               = false
Oct 29 14:17:50 9e73505334fa goatcounter[264]:                         version.version   = v2.7.0

HTTP 层验证(GoatCounter 按 Host 头路由站点,本机 curl 验证需带 -H 'Host: ...',实测回显):

# 1) 首页:未登录返回 303 跳转登录页
$ curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: stats.example.com' http://127.0.0.1:8135/
303
# 2) 登录页可达
$ curl -s -H 'Host: stats.example.com' http://127.0.0.1:8135/user/requestlogin | grep -oE '<title>[^<]*</title>'
<title>GoatCounter</title>
# 3) 埋点接口:模拟一次页面访问(返回 1x1 透明 GIF 即为接受)
$ curl -s -X POST 'http://127.0.0.1:8135/count' \
    -H 'Host: stats.example.com' \
    -H 'Content-Type: application/json' \
    -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20100101 Firefox/132.0' \
    -d '{"p":"/install-verify","t":"B1 verify","no_sessions":true}'
GIF89a

至此安装完成:生产环境把 stats.example.com 解析到本服务器后,浏览器直接访问 http://stats.example.com:8135/ 用 4.5 创建的 admin@example.com 登录即可看到仪表盘。若第 1 步不带 Host 头直接访问 IP,会得到 400 no site at this domain——这是设计行为,排障见 FAQ Q1。

五、方案 B:源码编译安装

5.1 方案说明

从官方源码 tag 自行编译出二进制。适用场景:目标平台没有官方预编译资产、需要在编译前修改/审计源码、或安全规范要求从源码构建。产物与官方二进制同源同功能,差别仅在体积裁剪与版本号注入方式(5.5)。

5.2 安装 Go 工具链

cd /tmp
# 官方 Go 发行包,59,768,009 字节
wget https://go.dev/dl/go1.25.5.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.25.5.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh
export PATH=$PATH:/usr/local/go/bin
go version

实测回显:

go version go1.25.5 linux/amd64

/usr/local/go 解压后占用约 243MB(实测 du -sh),仅构建机需要,运行服务器不需要装 Go。

5.3 安装编译依赖

GoatCounter 的 SQLite 驱动走 cgo(见 3 中 cgo=true),必须有 C 编译器与 libc 头文件:

apt-get update && apt-get install -y gcc libc6-dev
gcc --version | head -1

实测回显:

gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0

5.4 获取源码并编译

mkdir -p /opt/src && cd /tmp
# 下载 v2.7.0 源码归档(5,528,702 字节)
wget https://github.com/arp242/goatcounter/archive/refs/tags/v2.7.0.tar.gz \
     -O goatcounter-src-v2.7.0.tar.gz
tar -C /opt/src -xzf goatcounter-src-v2.7.0.tar.gz    # 得到 /opt/src/goatcounter-2.7.0
cd /opt/src/goatcounter-2.7.0
go build -o /opt/goatcounter-src ./cmd/goatcounter
echo "BUILD_EXIT=$?"

实测结果:6 核 CPU、全新模块缓存下完整构建约 6 分钟,产物 /opt/goatcounter-src 38,126,592 字节;之后增量重编译为秒级。

💡 网络受限环境必读(实测排障):go build 默认走 proxy.golang.org 模块代理,网络对 Google 系地址受限时会大量报 dial tcp 142.251.x.x:443: i/o timeout 后失败。实测在相同环境下把模块代理换成国内 goproxy.cn 即可一次通过:

GOPROXY=https://goproxy.cn,direct go build -o /opt/goatcounter-src ./cmd/goatcounter

完全离线的构建机则需先在联网机执行 go mod download(或 go mod vendor)后整体拷贝模块缓存(或 vendor 目录),再用 GOPROXY=off 构建。

此时验证产物:

$ /opt/goatcounter-src version
version=dev; go=go1.25.5; GOOS=linux; GOARCH=amd64; race=false; cgo=true

version=dev 不是 bug——见 5.5。

5.5 注入版本号(对齐官方 release 构建)

源码 context.go 中版本变量默认值为 "dev",官方发行构建通过 ldflags 注入 tag(源码注释原文:"which is done for release builds")。对齐官方做法重新编译并安装:

cd /opt/src/goatcounter-2.7.0
go build -ldflags "-X zgo.at/goatcounter/v2.Version=v2.7.0" \
         -o /usr/local/bin/goatcounter ./cmd/goatcounter
goatcounter version

实测回显(与官方二进制逐字段一致):

version=v2.7.0; go=go1.25.5; GOOS=linux; GOARCH=amd64; race=false; cgo=true

提示:自编产物默认 38MB(官方 28MB),是因为官方额外加了 -s -w 裁剪符号表;在意体积可把 ldflags 写成 -s -w -X zgo.at/goatcounter/v2.Version=v2.7.0。

5.6 与方案 A 的衔接

编译安装只改变 4.2–4.3 两步的产物来源;此后从 4.4(创建运行用户与数据目录)到 4.7(systemd 托管与验证)完全相同,不再重复。

六、方案对比与选择建议

维度方案 A:官方二进制方案 B:源码编译
交付形态官方 release 构建,v2.7.0 版本号内置自行构建,需 ldflags 注入版本号(否则显示 dev)
是否需编译环境否,解压即用Go 1.25.x(243MB)+ gcc/libc6-dev
联网需求仅下载 13.3MB 单文件(可完全离线搬运)需下载 Go 发行包 + Go 模块(可离线搬运但操作繁琐)
实测耗时分钟级(下载+解压)全新构建约 6 分钟(6 核)
产物体积28MB(官方已 -s -w 裁剪)36MB(未裁剪;自行加 -s -w 可对齐)
运行差异无(同源码同 Go 版本,version 回显逐字段一致)无
适用场景生产环境、快速部署(默认选择)官方未覆盖的平台、需要修改/审计源码、强合规要求源码构建
主要风险点依赖 GitHub 可达(或离线搬运)模块代理不可达需换 GOPROXY(见 5.4 排障实录)

选择建议:能用方案 A 就用方案 A——它与官方后续 release 的升级路径(替换二进制 + migrate)完全一致;方案 B 留给平台/合规/定制三类刚性需求。内网隔离环境优先方案 A 的离线搬运路径。

七、配置说明

7.1 配置方式总览

GoatCounter 没有配置文件,配置分三层(优先级从高到低):

  1. 命令行旗标(goatcounter serve -listen :8135 ...);
  2. 环境变量:每个旗标对应 GOATCOUNTER_<大写旗标名>(如 GOATCOUNTER_DB、GOATCOUNTER_LISTEN),适合受管环境/自动化注入;
  3. 站点级设置:存于数据库、经 Web 界面「Settings」修改(数据收集项、主题、retention 等)。

三层各自的完整清单、取值与生产模板见站内《GoatCounter 2.7.0 配置参数详解》,此处只覆盖安装期必须知道的子集。

7.2 安装期需要关注的参数

旗标默认值说明
-dbsqlite+./db.sqlite3存储连接串:SQLite 为 sqlite+<file>;PostgreSQL 为 postgres+<connect string>
-listen*:8080HTTP 监听地址,本文用 :8135
-public-port同 -listen对外公布端口(反代后与真实监听端口不同时设置)
-tlshttphttp / tls(自带 PEM)/ rdr(80 端口跳转)/ acme(自动证书)
-smtpstdout邮件发送方式;默认仅打印,生产配 smtp://用户:密码@主机:端口
-store-every10s内存缓冲落库周期,页访问先入内存再批量写库
-automigrate关启动时自动执行待定迁移(配合版本升级)
-ratelimit见配置篇各 API 域限流;导出默认 1 次/小时

7.3 systemd 配置覆写(drop-in)

不要直接改主单元文件,用 drop-in 覆写 ExecStart(实测可用,如放开导出限流):

mkdir -p /etc/systemd/system/goatcounter.service.d
cat > /etc/systemd/system/goatcounter.service.d/override.conf <<'EOF'
[Service]
ExecStart=
ExecStart=/usr/local/bin/goatcounter serve -listen :8135 -public-port 8135 -db sqlite+/var/lib/goatcounter/db.sqlite3 -ratelimit export:5/3600
EOF
systemctl daemon-reload && systemctl restart goatcounter

7.4 数据目录与备份策略

全部业务数据都在 /var/lib/goatcounter/db.sqlite3 单文件中(PostgreSQL 模式则在 PG 实例内)。SQLite 运行于 WAL 模式,在线热备用 SQLite 自带 backup 命令保证一致性(crontab 示例):

# 每日 03:10 一致性热备(不用停服务)
10 3 * * * sqlite3 /var/lib/goatcounter/db.sqlite3 ".backup '/var/backups/goatcounter-$(date +\%F).sqlite3'"

恢复 = 停服务 → 用备份文件覆盖数据文件 → 启服务。卸载/重装前的整体备份见第九章。

7.5 HTTPS 与反向代理要点

  • 直连模式:-tls acme 自动签发 Let's Encrypt 证书(需 80/443 可达且域名解析到位);已有证书用 -tls /path/fullchain.pem,/path/key.pem;
  • 反代模式:nginx/Caddy 反代到 -listen 端口,务必透传 Host 头(vhost 路由依据)与 WebSocket 升级头(仪表盘实时刷新用 WS);反代终止 TLS 时 GoatCounter 侧保持 -tls http 并用 -public-port/-base-path 对齐对外地址。详细配置模板见站内配置详解篇。

7.6 防火墙放行

ufw allow 8135/tcp    # 或仅放行反代来源 IP

八、常见问题(FAQ)

Q1:访问返回 400 no site at this domain ("127.0.0.1:8135")(或 400 no site at this domain ("<IP>:<port>"))? 这是 vhost 路由的设计行为:GoatCounter 按请求的 Host 头匹配站点域名。本机 curl 验证加 -H 'Host: stats.example.com'(见 4.7);生产环境把 stats.example.com 解析到服务器后用域名访问即可。站点与域名的对应关系可用 goatcounter db show site -find 1 查看(cname 字段即 vhost)。

Q2:想直接监听 80/443 端口? Linux 非 root 进程默认不能绑定 1024 以下端口。三选一:setcap cap_net_bind_service=+ep /usr/local/bin/goatcounter;systemd 单元加 AmbientCapabilities=CAP_NET_BIND_SERVICE;或(推荐)保持高位端口 + 前置 nginx/Caddy 反代终止 TLS。

Q3:忘记管理员密码,或需要新增一个管理员? CLI 直接增删,无需邮件流程。新增管理员(实测回显:成功静默,exit 0):

$ goatcounter db create user \
    -db 'sqlite+/var/lib/goatcounter/db.sqlite3' \
    -site 1 -email reset-admin@example.com \
    -password 'q1w2e3r4' -access admin
$ goatcounter db query -db 'sqlite+/var/lib/goatcounter/db.sqlite3' \
    "select user_id, email, site_id, access from users;"
user_id  email                    site_id  access
1        admin@example.com        1        {"all":"*"}
3        reset-admin@example.com  1        {"all":"a"}

-access 取值 readonly / settings / admin / superuser,缺省时报错 -access: must be set。新账号走登录页的「Forgot password」流程或直接使用 -password 设定的口令登录。

Q4:systemctl start goatcounter 失败? 按 journalctl -u goatcounter -e 从后往前看,常见三类:数据目录不存在或属主不是 goatcounter(permission denied);-db 连接串少了 sqlite+ 前缀导致解析失败;库文件不存在(首次初始化要用 db create site ... -createdb,见 4.5)。另注意环境变量 GOATCOUNTER_DB 若已设置而命令行又没写 -db,会用环境变量的值——排查时先用 systemctl show goatcounter -p Environment 确认。

Q5:导出的 CSV 是空的? v2.7.0 默认出于隐私只存小时级聚合计数,不落单条浏览明细(导出的 CSV 就是这份明细)。需要在站点设置勾选 "Individual pageviews" 才开始记录;机制与位掩码细节见站内《GoatCounter 2.7.0 配置参数详解》的 collect 参数章节。

Q6:源码编译后 goatcounter version 显示 version=dev? 未注入版本号的正常现象,不影响任何功能;按 5.5 用 -ldflags "-X zgo.at/goatcounter/v2.Version=v2.7.0" 重编译即可与官方回显一致。

九、卸载与清理

按顺序执行(先备份数据再删除):

# 1. 停服务并移除自启
systemctl disable --now goatcounter

# 2. 备份数据目录(按需保留)
tar -czf /root/goatcounter-data-backup-$(date +%F).tar.gz -C /var/lib goatcounter

# 3. 删除 systemd 单元与 drop-in
rm -f /etc/systemd/system/goatcounter.service
rm -rf /etc/systemd/system/goatcounter.service.d
systemctl daemon-reload && systemctl reset-failed

# 4. 删除程序与数据
rm -f /usr/local/bin/goatcounter
rm -rf /var/lib/goatcounter

# 5. 删除运行用户
userdel goatcounter

方案 B 额外清理构建环境:rm -rf /usr/local/go /opt/src/goatcounter-2.7.0,Go 模块缓存默认在 $HOME/go/pkg/mod(构建机不再编译 Go 程序可整体删除)。

十、参考链接