配置Openfga
部署Openfga之前,我们需要先去配置数据库,不然的话,会默认使用内存作为数据库。
OpenFGA支持多种数据库,如PostgreSQL 14, MySQL 8 和 SQLite。
官方提供了三种配置方式:
- 配置文件
- 环境变量
- 命令行
本文只介绍配置文件,其他配置可参考openfga.dev/docs/gettin…
配置文件的方式: 在本地启动的话,新建一个config.yaml放到项目文件夹的工作区中 内容如下:
datastore:
engine: postgres
uri: postgres://user:password@localhost:5432/mydatabase
authn:
method: preshared
preshared:
keys: ["key1", "key2"]
上面是指定数据库引擎以及数据库配置,下面是用于客户端的权限配置,权限配置可以参考(openfga.dev/docs/gettin…
部署
打包部署OpenFGA
部署到Linux的话,需要将项目打包为二进制文件,然后上传到Linux下
可以使用打包命令
go build // 在openfga目录下,默认打出的可执行文件名称是openfga(windows 是 openfga.exe)
go build main.go //这个命令,打出的是名称是 main(windows 是 main.exe)
go build -o myapp // 这个命令指定打出的可执行文件名称是 myapp
go build -o ./bin/myapp //指定文件的生成路径
将生成的二进制文件通过SFTP的工具,移动到linux的文件目录下,这里我放到了/opt/openfga目录下。
配置文件
将配置文件放到指定目录下。
我们需要将我们之前写好的配置文件config.yaml放到openfga可以找到的地方。
openfga默认通过三种方式并且按照顺序查找配置文件:
/etc/openfga
$HOME/.openfga
- 当前工作的文件夹目录。
放好文件后,我们启动openFGA.
启动Openfga
我们移动到openFGA的二进制文件目录下,使用命令
./openfga run
即可成功运行。
启动脚本
对于启动的命令,我们可以封装为一个脚本start_openfga.sh
,下次直接运行脚本即可,以下是DeepSeek生成的脚本,用于启动OpenFGA并且追加日志
#!/bin/bash
# 定义日志文件路径
LOG_DIR="/opt/openfga/logs"
LOG_FILE="$LOG_DIR/openfga.log"
# 检查日志文件所在目录是否存在,如果不存在则创建
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
# 检查日志文件是否存在,如果不存在则创建空文件
if [ ! -f "$LOG_FILE" ]; then
touch "$LOG_FILE"
fi
# 启动 OpenFGA 服务并将输出重定向到日志文件
nohup ./openfga run --profiler-enabled --profiler-addr :3002 --playground-enabled --playground-port 3001 &> "$LOG_FILE" &
# 输出提示信息
echo "OpenFGA 服务已在后台启动,日志输出到 $LOG_FILE"
~
对于脚本的启动也可以使用命令重命名来快速启动,并且打印日志
alias startOpenfga='/opt/openfga/start_openfga.sh && tail -f /opt/openfga/logs/openfga.log'
部署时可能会遇到的问题
1. openfga启动不了
如果提示
bash: ./main: cannot execute binary file: Exec format error
一般这种情况是可执行文件的架构与 Linux 服务器的架构不兼容。检查一下打的包是否正确:
在服务器上执行:
uname -m
常见输出:
x86_64
:64 位 Intel/AMD 系统。aarch64
:64 位 ARM 架构(如 AWS Graviton、树莓派 4)。
然后检查可执行文件的架构
在本地编译的 main
文件所在目录执行:
file main
输出示例:
-
不兼容的情况:
main: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows # 这是 Windows 可执行文件 main: Mach-O 64-bit executable x86_64 # 这是 macOS 可执行文件
-
兼容的情况:
main: ELF 64-bit LSB executable, x86-64, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=...
解决方法 指定编译环境
# 明确指定目标平台(如 Linux x86_64)
GOOS=linux GOARCH=amd64 go build -o openfga
2. 与数据库数据不一致(数据为空)
这种情况一般是config.yaml
未能放到正确的位置,检查一下config.yaml是否符合上述所描述的三种位置(我一般建议你直接放到/etc/openfga/目录下)
3. OpenFGA的PlayGround用不了
访问 http://ip/3000/playground, 却发现弹出以下提示:
打开控制台发现:
到这里你可能怀疑是不是哪一步出错了,不,你没错!
到目前这一步说明Openfga成功部署了,问题在于playground上面,playground只允许localhost进行访问。
官网中的描述:
通过在OpenFGA的issue上面的查找,发现
OpenFGA的开发人员认为,将playground暴露给其他ip可能会有安全的风险(因为其他人可以直接改动目前正在使用的model的Tuple数据)
也就是说我们将Openfga部署到服务器上后,无法在除了服务器本身的地方使用playground。
但同时官方也提供了替代方案:
详情可以查看一下这个issue:github.com/openfga/ope…
但是官方其实将palyground开源加入了他们的计划表(优先级不高)
详细讨论可以参照 github.com/orgs/openfg…
OpenFGA的项目经理认为这个功能非核心,且由于使用了他们的内部库,导致如果要开源就要大量的重写代码。
但是也有人提出了其中一种访问服务器playground的解决方法,如下:
OpenFGA的局限性
水平部署
目前OpenFGA没有提供水平多机部署的示例,不过应该也很好做,找一个负载均衡的中间件使用即可
分布式缓存
目前OpenFGA还不支持分布式缓存,这导致多机部署的话,缓存会出现不一致性(缓存失效的通知问题,或者分布式缓存)。
官方目前已经将分布式缓存加入了roadmap中,但是不知道什么时候能够上线,所以后续我们开发时,就需要自己修改OpenFGA源码去实现分布式缓存。
补充
stop脚本
我之前是直接使用打好的包进行启动的,所以可以使用一个shell脚本来执行stop操作。
shell脚本如下
#!/bin/bash
# 脚本功能:精准停止所有通过 "main" 进程运行的 OpenFGA 服务
# 适用场景:二进制部署的 OpenFGA,进程名称为 main
# -------------------------- 核心逻辑 --------------------------
# 1. 精准匹配进程(避免误杀其他名为 main 的进程)
# 假设 OpenFGA 启动命令包含特征参数(例如 "--config")
OPENFGA_PIDS=$(pgrep -f "main.*(run|start|--config)")
if [ -z "$OPENFGA_PIDS" ]; then
echo "No running OpenFGA (main) processes found."
exit 0
fi
# 2. 优雅终止进程
echo "Stopping OpenFGA processes (PIDs: $OPENFGA_PIDS)..."
kill -15 $OPENFGA_PIDS # 发送 SIGTERM 信号
# 3. 等待进程退出(最长等待 10 秒)
timeout=10
end_time=$(( $(date +%s) + timeout ))
for PID in $OPENFGA_PIDS; do
# 等待进程自然退出
while [ $(date +%s) -lt $end_time ]; do
if ! ps -p $PID > /dev/null; then
echo "Process $PID exited gracefully."
break
fi
sleep 1
done
# 超时后强制终止
if ps -p $PID > /dev/null; then
echo "Force killing PID $PID (did not exit in $timeout seconds)..."
kill -9 $PID
fi
done
echo "All OpenFGA (main) processes stopped."
重启脚本
直接将关闭和启动合二为一,先关闭,再启动
#!/bin/bash
# OpenFGA 重启脚本(支持自定义二进制名称)
# 配置区(用户可修改以下变量)
BINARY_NAME="openfga" # 在此处修改二进制文件名
LOG_DIR="/opt/openfga/logs" # 日志目录
LOG_FILE="$LOG_DIR/${BINARY_NAME}.log" # 自动生成日志路径
# 获取精确进程ID
get_pid() {
pgrep -f "^\./${BINARY_NAME} run" # 精确匹配启动命令
}
# 终止旧进程
stop_service() {
local pid=$(get_pid)
[ -n "$pid" ] && {
echo "终止运行中的 $BINARY_NAME (PID: $pid)"
kill -15 $pid 2>/dev/null && sleep 2
# 双重确认强制终止
if pgrep -f "^\./${BINARY_NAME} run" >/dev/null; then
kill -9 $pid 2>/dev/null
sleep 1
fi
}
}
# 启动新进程
start_service() {
# 确保日志目录存在
mkdir -p "$LOG_DIR"
[ ! -f "$LOG_FILE" ] && touch "$LOG_FILE"
nohup "./${BINARY_NAME}" run --profiler-enabled --profiler-addr :3002 \
--playground-enabled --playground-port 3001 &>> "$LOG_FILE" &
}
# 主流程
stop_service
start_service
# 结果检查
if get_pid >/dev/null; then
echo "重启成功!PID: $(get_pid), 日志: $LOG_FILE"
else
echo "重启失败,请检查日志: $LOG_FILE"
exit 1
fi