GoatCounter 2.7.0 配置参数详解

GoatCounter 2.7.0 配置参数详解:serve 全部旗标、GOATCOUNTER_ 前缀环境变量、SQLite/PostgreSQL 连接串与站点级设置逐项实测,附生产配置模板。

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

GoatCounter 2.7.0 配置参数详解

目标:把 GoatCounter v2.7.0 goatcounter serve 的全部命令行旗标、GOATCOUNTER_ 环境变量与站点级设置讲透——每个参数给出官方语义、默认值与实测验证,读完后能独立完成从单机 SQLite 到 PostgreSQL 的生产化配置。文中所有命令与回显均在 Ubuntu 24.04.5 LTS 服务器上实测取得,版本 v2.7.0。

一、环境信息

  • 操作系统:Ubuntu 24.04.5 LTS(cat /etc/os-release 实测),x86_64
  • GoatCounter:v2.7.0 官方预编译二进制,安装于 /usr/local/bin/goatcounter(goatcounter version 实测:version=v2.7.0; go=go1.25.5; GOOS=linux; GOARCH=amd64; race=false; cgo=true)
  • 数据目录:/var/lib/goatcounter,SQLite 库文件 db.sqlite3;运行用户 goatcounter(系统用户)
  • Web 监听端口:8135(-listen :8135),PostgreSQL 附加实验端口 8136
  • 附加组件(PostgreSQL 实验用):PostgreSQL 16.15(apt 安装),库名 goatcounter
  • 服务托管:systemd 单元 goatcounter.service(安装篇已建),systemctl is-active goatcounter 实测 active

安装步骤、systemd 单元与建站过程不在本文重复,见《Ubuntu 24.04 安装 GoatCounter 2.7.0 指南》;每个参数在 CLI 层面的使用示例见《GoatCounter 2.7.0 常用 CLI 命令与工具详解》。

二、前置条件

  • 已按安装篇完成二进制安装、建站(db create site)并能正常启动服务。
  • 能读取服务日志:systemd 部署用 journalctl -u goatcounter,前台运行则直接看终端。 GoatCounter 启动时会把关键配置回显到日志,是核对配置生效的首要手段(实测节选):
Oct 29 14:17:50  INFO  startup: GoatCounter ready
                        num_sites         = 1
                        sites             = [stats.example.com]
                        listen            = :8135
                        dev               = false
                        version.version   = v2.7.0
                        version.go        = go1.25.5
                        version.GOOS      = linux
                        version.GOARCH    = amd64
                        version.CGO       = true
                        version.race      = false
                        geoip.path        =
                        geoip.build       = 2025-05-20 09:30:47
                        geoip.type        = GeoLite2-Country
  • 了解两层配置的边界:服务级配置(serve 的旗标/环境变量,影响整个进程:数据库、监听、TLS、SMTP、限流)与站点级设置(Web 界面 Settings 或 sites.settings JSON 列,按站点生效:数据收集项、公开性、数据保留)。本文主体讲服务级,第 6 章讲站点级。

三、参数查看与修改方式

  1. 查看全部旗标与默认值:goatcounter help serve(或 goatcounter serve -h)。官方建议细读的三个专题帮助:goatcounter help listen(监听与 TLS)、goatcounter help db(数据库连接串)、goatcounter help debug(调试模块)。以下为 goatcounter serve -h 实测的旗标清单(节选,完整 18 个旗标逐项见第 5 章):
  -db          Database connection: "sqlite+<file>" or "postgres+<connect>"
  -dbconn      Set maximum number of connections, as max_open,max_idle
  -listen      Address to listen on. Default: "*:8080".
  -tls         Serve over tls. ...
  -public-port Port your site is publicly accessible on. ...
  -base-path   Path under which GoatCounter is available. ...
  -automigrate Automatically run all pending migrations on startup.
  -smtp        SMTP relay server, as URL (e.g. "smtp://user:pass@server:port"). ...
  -email-from  From: address in emails. Default: <user>@<hostname>
  -errors      What to do with errors; ...
  -static      Serve static files from a different domain, ...
  -geodb       Path to mmdb GeoIP database; ...
  -ratelimit   Set rate limits for various actions; ...
  -api-max     Maximum number of items /api/ endpoints will return. ...
  -store-every How often to persist pageviews to the database, in seconds.
  -dev         Start in "dev mode".
  -json        Output logs as JSON instead of aligned text.
  -debug       Modules to debug, comma-separated or 'all' for all modules.
  1. 修改方式:改 systemd 单元的 ExecStart 行(推荐,安装篇即此形态),或改环境变量(第 4 章),改完 systemctl daemon-reload && systemctl restart goatcounter。GoatCounter 没有 nginx -t 那样的配置预检命令,配置是否生效以启动日志回显为准。

  2. 验证是否生效:重启后 journalctl -u goatcounter -n 20 --no-pager 核对回显(如 listen = :8135),再 curl -I http://stats.example.com:8135/(实测返回 HTTP/1.1 303,重定向到登录页 /user/new,属正常现象)。

四、环境变量(GOATCOUNTER_ 前缀)

官方设计:serve 的每个旗标都可以用 GOATCOUNTER_«旗标名大写» 环境变量给默认值,命令行旗标优先于环境变量。官方帮助原文(goatcounter help serve 实测):

Environment:

  All of the flags take the defaults from $GOATCOUNTER_«FLAG», where «FLAG» is
  the flag name. The commandline flag will override the environment variable.

  For example:

    GOATCOUNTER_LISTEN=:80
    GOATCOUNTER_STORE_EVERY=60
    GOATCOUNTER_AUTOMIGRATE=

实测验证环境变量确实生效(用 db test 与 GOATCOUNTER_DB 演示,错误信息中可以看到连接串已被环境变量替换):

$ GOATCOUNTER_DB="sqlite+/tmp/envtest.sqlite3" goatcounter db test
goatcounter: zdb.Connect: sqlite3 database "/tmp/envtest.sqlite3" doesn't exist (from connection string "sqlite3:file:/tmp/envtest.sqlite3?...")
(exit=1:库不存在,但连接串已被 GOATCOUNTER_DB 覆盖,证明前缀生效)

另有两个特殊环境变量(官方帮助原文):

  • GOATCOUNTER_API_KEY:import、dashboard 子命令用的 API 令牌(需要相应权限)。
  • GOATCOUNTER_TMPDIR / TMPDIR:临时文件目录,目前用于 CSV 导出中间文件(实测导出时在 /tmp 生成 goatcounter-export-serve-...-0.csv.gz)。

💡 技术拓展:十二要素应用(12-Factor App)推荐用环境变量注入配置而非命令行参数,GoatCounter 两者都支持。实践中推荐分工:易变的部署参数(监听地址、数据库)写 systemd Environment= 行,敏感凭据(数据库密码、SMTP 密码)也走环境变量避免出现在 ps 输出里——命令行参数对本机所有用户可见,这是选择环境变量的安全理由;而需要随版本固定、希望一眼看到的(如 -automigrate)留在 ExecStart。

systemd 注入示例(每行一个 Environment=):

[Service]
Environment=GOATCOUNTER_LISTEN=:8135
Environment=GOATCOUNTER_DB=sqlite+/var/lib/goatcounter/db.sqlite3
Environment=GOATCOUNTER_AUTOMIGRATE=true

五、核心参数分类详解

5.1 数据库:-db 与 -dbconn

-db 是最核心的参数,连接串格式 sqlite+<文件> 或 postgres+<连接串>。官方帮助原文要点 + 实测:

-db          Database connection: "sqlite+<file>" or "postgres+<connect>"
             See "goatcounter help db" for detailed documentation. Default:
             sqlite+./db/goatcounter.sqlite3 if that database file exists, or
             sqlite+./goatcounter-data/db.sqlite3 if it doesn't.

注意默认值的探测逻辑:工作目录下存在 ./db/goatcounter.sqlite3 用之,否则用 ./goatcounter-data/db.sqlite3。生产建议显式指定绝对路径,避免工作目录漂移导致"换了库"。实测默认行为(未指定 -db 时 db test 的报错原文,可以看到默认连接串与全部默认驱动参数):

$ goatcounter db test
goatcounter: zdb.Connect: sqlite3 database "/goatcounter-data/db.sqlite3" doesn't exist
(from connection string "sqlite3:file:./goatcounter-data/db.sqlite3?_busy_timeout=200&_cache_size=-20000&_case_sensitive_like=on&_defer_foreign_keys=on&_foreign_keys=on&_journal_mode=wal")

SQLite 模式三个官方调整过的默认参数(help db 原文,可按需覆盖):

参数默认官方说明
_journal_modewalWAL 通常更快、并发更好,对小站几乎没有代价
_busy_timeout200锁等待 200ms 而非立刻报错
_cache_size-2000020MB 页缓存(SQLite 默认 2MB),官方称常有明显性能收益

覆盖示例(回到 SQLite 原生默认,官方帮助原文):-db 'sqlite+mydb.sqlite?_journal_mode=delete&_busy_timeout=0&_cache_size=-2000'。

PostgreSQL 模式实测全流程(Ubuntu 24.04 + PostgreSQL 16.15):建用户建库后直接迁移建站:

goatcounter db migrate all -createdb \
  -db "postgresql+postgres://goatcounter:q1w2e3r4@localhost:5432/goatcounter?sslmode=disable"
goatcounter db test \
  -db "postgresql+postgres://goatcounter:q1w2e3r4@localhost:5432/goatcounter?sslmode=disable"

实测回显:

DB at "postgresql+postgres://goatcounter:q1w2e3r4@localhost:5432/goatcounter?sslmode=disable" seems okay; pq version 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)

PostgreSQL 模式同样实测通过 db create site 建站与 serve 对外服务(监听 :8136,GET /user/new 返回 200)。官方调优建议(help db 原文):GoatCounter 的部分查询计划器倾向顺序扫描,建议 alter database goatcounter set seq_page_cost=1.1;。SQLite 转 PostgreSQL 官方路径是 pgloader(先手工建 schema、清空 locations/languages 两表再转换,help db 有完整步骤)。

-dbconn:连接池上限,格式 max_open,max_idle,默认 16,4;-1 表示不设限/不保留空闲连接。SQLite 模式下意义不大,PostgreSQL 高并发场景按 max_open 保护数据库。

5.2 监听与 TLS:-listen、-tls、-public-port、-base-path

-listen 默认 *:8080,语法与常见工具一致(help listen 原文):

    -listen localhost:8081     Listen on localhost:8081
    -listen :8081              Listen on :8081 for all addresses

-tls 是逗号列表,取值与组合语义如下(help listen 原文归纳):

取值作用
http不启用 TLS(默认)
tls在 -listen 端口上直接接受 TLS
rdr把 80 端口重定向到 -listen 端口(301)
acme[:目录]用 ACME(Let's Encrypt)自动签证书;缓存目录默认 ./acme-secrets 或 ./goatcounter-data/acme-secrets,须保密;要求 80 端口可公网访问以完成质询
path/to/file.pem使用自有证书(证书+私钥合一文件),可多次给出

官方给的三种典型组合(help listen 原文):-listen :443 -tls tls,rdr,acme(全自动 HTTPS)、-listen :443 -tls tls,rdr,/etc/tls/stats.example.com.pem(自有证书)、反代场景 goatcounter serve -listen localhost:8081 -tls none 后由 nginx/Caddy 管 TLS——反代需转发 X-Forwarded-Proto: https 与 X-Forwarded-For,并建议允许 WebSocket(仪表盘实时刷新依赖)。

-public-port:当对外端口不是 80/443 时必须声明,否则重定向、邮件里的链接端口不对。官方原文:goatcounter serve -listen :9000 -public-port 9000。本文实测环境正是此形态:-listen :8135 -public-port 8135,浏览器访问 http://stats.example.com:8135/ 全流程正常。

-base-path:需要挂在子路径(如 example.com/stats)时设为 /stats;独立域名/子域部署不需要。

5.3 邮件:-smtp 与 -email-from

-smtp 默认 stdout——不发真邮件,把邮件内容打到标准输出(help serve 原文:"A special value of "stdout" or "stderr" will print emails to stdout or stderr without actually sending them. The default is "stdout"")。生产接真实中继示例:-smtp smtp://user:pass@server:port(支持 smtps:// 与 STARTTLS;URL 加 ?debug=1 可把客户端/服务端报文打印到 stderr)。-email-from 默认 <user>@<hostname>,正式使用建议显式指定如 -email-from stats@example.com。未配置真实 SMTP 时,登录/找回密码邮件会在日志里打印而非投递——首次部署"收不到邮件"先查这里。

5.4 限流与 API:-ratelimit 与 -api-max

-ratelimit 官方默认(help serve 原文实测照抄):

    count:4/1            4 requests / second
    api:4/1              4 requests / seconds
    api-count:60/120    60 requests / 2 minutes
    export:1/3600        1 requests / hour
    login:20/60         20 requests / minute

实测触发过限流:连续第二次调用导出 API 返回

{"error": "rate limited exceeded; try again in 59m54.22651952s"}

应对方式即官方注释所述:部分覆盖默认值,如 -ratelimit export:5/3600,api:100/1(未提到的项回落默认)。大量历史导入时官方明确建议临时调高 api-count(help import 原文示例:goatcounter serve -ratelimit api-count:1000/1 ...)。

-api-max:/api/ 端点单次返回条数上限,默认 200(paths)/100(其他);0 恢复默认,负数不限。

5.5 数据写入节奏:-store-every

-store-every 默认 10 秒:页面访问先进内存,10 秒批量落库(官方原文:调大性能更好,但统计延迟变长)。实测与该机制完全吻合:发一个 /count 后立即查库为 0 行,约 10 秒后聚合计数与明细出现。因此部署后"看不到刚点的访问"是设计行为,也是 monitor 巡检命令要考虑的窗口。

5.6 杂项:-automigrate、-errors、-static、-geodb、-dev、-json、-debug

  • -automigrate:启动时自动跑未执行的数据库迁移;升级版本时配合 systemd 最省事(官方 migrate 帮助注明可代替手工 db migrate all)。
  • -errors:错误除打印 stderr 外可邮件告警:-errors mailto:ops@example.com。
  • -static:静态资源走独立域/CDN(cookieless 域名场景)。
  • -geodb:城市级 GeoIP 库路径,或 maxmind:账号:密钥[:路径] 自动下载每周更新的 Cities 库;不指定则用内置 GeoLite2-Country(只到国家级,实测启动日志 geoip.type = GeoLite2-Country)。
  • -dev:开发模式(模板/静态资源从文件系统加载),生产不要开。
  • -json:日志输出为 JSON(接日志采集器时用)。
  • -debug:调试模块,逗号分隔或 all。模块清单(help debug 原文节选):cron、dashboard、export、import、import-api、memstore(页面落库)、migrate、monitor、session、sql-query、sql-result、vacuum 等。

六、站点级设置(sites.settings)

服务级参数管进程,站点级设置管"一个站点收集什么、给谁看",存于 sites.settings JSON 列,Web 界面 Settings 页修改,CLI 可用 db show site 查看。实测样例(v2.7.0 新建站点):

{"public":"private","secret":"","allow_counter":false,"allow_bosmang":false,
 "data_retention":0,"ignore_ips":"","collect":190,"collect_regions":"US,RU,CN","allow_embed":""}

逐项说明:

键默认含义
publicprivate仪表盘是否公开可看(public 时他人可访问只读视图,可配 secret)
collect190数据收集位掩码(见下)
collect_regionsUS,RU,CN需要细化到地区的国家
data_retention0数据保留月数,0=永久;超出自动清理
ignore_ips空不统计的 IP/CIDR 列表(自家办公室访问)

collect 位掩码是 v2.7.0 最值得注意的行为(源码 settings.go 定义):1=不收集、2=Referrer、4=User-Agent、8=屏幕尺寸、16=国家、32=地区、64=语言、128=会话(8 小时唯一访客)、256=原始页面明细(Individual pageviews)。默认 190=2+4+8+16+32+128——不含 256,即默认只存聚合统计、不存逐条访问明细(导出 CSV 会是空文件,实测踩点)。开启方法:Web 界面 Settings 勾选 "Individual pageviews" 后 collect 变为 446,hits 明细表开始写入(实测:开启前 select count(*) from hits 为 0,开启并访问后为 1,导出 num_rows 从 0 变 1)。这一默认是隐私设计:仪表盘、API 聚合统计不受影响,只有 CSV 导出依赖明细。

💡 技术拓展:站点级 data_retention 与自建统计的合规取舍。常见策略对比——永久保留(最简单,库无限涨)、按月滚动清理(如 24 个月,Matomo/GoatCounter 均内置)、只存聚合不存明细(GoatCounter v2.7.0 默认,无法回溯逐条但合规面最小)。本方案默认"只聚合 + 永久聚合",如需导出再临时开启明细。

七、生产配置模板

模板 A:小站 SQLite(≤1GB 内存,日均 PV < 50 万)——systemd ExecStart 一行配置即可:

ExecStart=/usr/local/bin/goatcounter serve \
  -listen :8135 -public-port 8135 \
  -db sqlite+/var/lib/goatcounter/db.sqlite3 \
  -dbconn 16,4 \
  -automigrate \
  -smtp smtp://user:pass@smtp.example.com:587 \
  -email-from stats@example.com

要点:SQLite WAL 默认已调优(20MB 缓存);-automigrate 让升级免手工迁移;SQLite 数据目录与库文件纳入日常备份(sqlite3 .backup 或停服拷贝,见安装篇)。

模板 B:中型站 PostgreSQL(日均 PV 百万级,4GB+ 内存独立 PG):

ExecStart=/usr/local/bin/goatcounter serve \
  -listen localhost:8080 -tls http \
  -db postgresql+postgres://goatcounter:${GOATCOUNTER_PG_PASS}@db.internal:5432/goatcounter?sslmode=verify-full \
  -dbconn 32,8 \
  -automigrate \
  -ratelimit api-count:1000/1 \
  -json \
  -errors mailto:ops@example.com
Environment=GOATCOUNTER_PG_PASS=<由 systemd EnvironmentFile 注入>

要点:置于 nginx 之后(TLS 交给反代,转发 X-Forwarded-Proto/For,允许 WebSocket);-dbconn 按 PG 承压能力放宽;-json 便于日志采集;sslmode 按内网实际选择(verify-full 需签发受信证书)。官方对 PG 的额外调优:alter database goatcounter set seq_page_cost=1.1;。

八、常见问题

Q1:访问显示空白/404,日志出现 "Accessing the site on domain ..." 警告。 站点按 vhost 匹配,用未配置的域名(如 127.0.0.1)访问会有警告(实测日志原文):WARN Accessing the site on domain "127.0.0.1", but the configured domain is "stats.example.com". This will work fine as long as you only have one site, but you *need* to use the configured domain if you add a second site。单站点不影响使用;多站点必须用配置域名访问(hosts/DNS 指过来)。

Q2:导出 CSV 是空的(num_rows=0)。 v2.7.0 默认 collect=190 不含原始明细(256)。开启 Settings → "Individual pageviews" 后重新访问积累数据即可(实测验证,见第六章)。

Q3:API 报 "rate limited exceeded; try again in 59m..."。 export:1/3600 默认每小时一次导出。临时放宽:-ratelimit export:5/3600(实测有效),或等待窗口重置。

Q4:改了配置不生效。 GoatCounter 无配置预检命令,先确认改的是进程实际使用的启动方式(systemd 单元 vs 手工命令行),重启后以 journalctl -u goatcounter 启动回显为准(listen、num_sites 等都会打印)。

Q5:收不到登录/报告邮件。 默认 -smtp stdout 只打印不投递(实测与官方帮助一致)。配置真实 SMTP 中继并用 journalctl 观察投递日志;调试可在 URL 加 ?debug=1。

九、参考链接