opengfw: remove (#500273)

This commit is contained in:
dram
2026-03-24 07:29:05 +00:00
committed by GitHub
7 changed files with 8 additions and 453 deletions
@@ -189,7 +189,7 @@
- [Improved File Manager (IFM)](https://github.com/misterunknown/ifm), a single-file web-based file manager. Available as [services.ifm](options.html#opt-services.ifm.enable).
- [OpenGFW](https://github.com/apernet/OpenGFW), an implementation of the Great Firewall on Linux. Available as [services.opengfw](#opt-services.opengfw.enable).
- [OpenGFW](https://github.com/apernet/OpenGFW), an implementation of the Great Firewall on Linux. Available as `services.opengfw`.
- [Rathole](https://github.com/rapiz1/rathole), a lightweight and high-performance reverse proxy for NAT traversal. Available as [services.rathole](#opt-services.rathole.enable).
@@ -223,6 +223,8 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
- `lunarvim` package has been removed, as it was abandoned upstream and relied on an old version of `neovim` to work properly.
- `opengfw` package and `services.opengfw` module have been removed as the upstream GitHub repository and website have been shut down.
## Other Notable Changes {#sec-release-26.05-notable-changes}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
-1
View File
@@ -1329,7 +1329,6 @@
./services/networking/oink.nix
./services/networking/onedrive.nix
./services/networking/openconnect.nix
./services/networking/opengfw.nix
./services/networking/openvpn.nix
./services/networking/opkssh/opkssh.nix
./services/networking/ostinato.nix
+4
View File
@@ -452,6 +452,10 @@ in
(mkRemovedOptionModule [ "services" "gateone" ] ''
The gateone module was removed since the package was removed alongside much other obsolete python 2.
'')
(mkRemovedOptionModule [ "services" "opengfw" ] ''
The opengfw package and services.opengfw module have been removed since the upstream
GitHub repository and website have been shut down.
'')
(mkRemovedOptionModule [ "virtualisation" "lxd" ] ''
LXD has been removed from NixOS due to lack of Nixpkgs maintenance.
Consider migrating or switching to Incus, or remove from your configuration.
@@ -1,414 +0,0 @@
{
lib,
pkgs,
config,
...
}:
let
inherit (lib)
mkOption
types
mkIf
optionalString
;
cfg = config.services.opengfw;
in
{
options.services.opengfw = {
enable = lib.mkEnableOption ''
OpenGFW, A flexible, easy-to-use, open source implementation of GFW on Linux
'';
package = lib.mkPackageOption pkgs "opengfw" { default = "opengfw"; };
user = mkOption {
default = "opengfw";
type = types.singleLineStr;
description = "Username of the OpenGFW user.";
};
dir = mkOption {
default = "/var/lib/opengfw";
type = types.singleLineStr;
description = ''
Working directory of the OpenGFW service and home of `opengfw.user`.
'';
};
logFile = mkOption {
default = null;
type = types.nullOr types.path;
example = "/var/lib/opengfw/opengfw.log";
description = ''
File to write the output to instead of systemd.
'';
};
logFormat = mkOption {
description = ''
Format of the logs. [logFormatMap](https://github.com/apernet/OpenGFW/blob/d7737e92117a11c9a6100d53019fac3b9d724fe3/cmd/root.go#L62)
'';
default = "json";
example = "console";
type = types.enum [
"json"
"console"
];
};
pcapReplay = mkOption {
default = null;
example = "./opengfw.pcap";
type = types.nullOr types.path;
description = ''
Path to PCAP replay file.
In pcap mode, none of the actions in the rules have any effect.
This mode is mainly for debugging.
'';
};
logLevel = mkOption {
description = ''
Level of the logs. [logLevelMap](https://github.com/apernet/OpenGFW/blob/d7737e92117a11c9a6100d53019fac3b9d724fe3/cmd/root.go#L55)
'';
default = "info";
example = "warn";
type = types.enum [
"debug"
"info"
"warn"
"error"
];
};
rulesFile = mkOption {
default = null;
type = types.nullOr types.path;
description = ''
Path to file containing OpenGFW rules.
'';
};
settingsFile = mkOption {
default = null;
type = types.nullOr types.path;
description = ''
Path to file containing OpenGFW settings.
'';
};
settings = mkOption {
default = null;
description = ''
Settings passed to OpenGFW. [Example config](https://gfw.dev/docs/build-run/#config-example)
'';
type = types.nullOr (
types.submodule {
options = {
replay = mkOption {
description = ''
PCAP replay settings.
'';
default = { };
type = types.submodule {
options = {
realtime = mkOption {
description = ''
Whether the packets in the PCAP file should be replayed in "real time" (instead of as fast as possible).
'';
default = false;
example = true;
type = types.bool;
};
};
};
};
io = mkOption {
description = ''
IO settings.
'';
default = { };
type = types.submodule {
options = {
queueSize = mkOption {
description = "IO queue size.";
type = types.int;
default = 1024;
example = 2048;
};
local = mkOption {
description = ''
Set to false if you want to run OpenGFW on FORWARD chain. (e.g. on a router)
'';
type = types.bool;
default = true;
example = false;
};
rst = mkOption {
description = ''
Set to true if you want to send RST for blocked TCP connections, needs `local = false`.
'';
type = types.bool;
default = !cfg.settings.io.local;
defaultText = "`!config.services.opengfw.settings.io.local`";
example = false;
};
rcvBuf = mkOption {
description = "Netlink receive buffer size.";
type = types.int;
default = 4194304;
example = 2097152;
};
sndBuf = mkOption {
description = "Netlink send buffer size.";
type = types.int;
default = 4194304;
example = 2097152;
};
};
};
};
ruleset = mkOption {
description = ''
The path to load specific local geoip/geosite db files.
If not set, they will be automatically downloaded from [Loyalsoldier/v2ray-rules-dat](https://github.com/Loyalsoldier/v2ray-rules-dat).
'';
default = { };
type = types.submodule {
options = {
geoip = mkOption {
description = "Path to `geoip.dat`.";
default = null;
type = types.nullOr types.path;
};
geosite = mkOption {
description = "Path to `geosite.dat`.";
default = null;
type = types.nullOr types.path;
};
};
};
};
workers = mkOption {
default = { };
description = "Worker settings.";
type = types.submodule {
options = {
count = mkOption {
type = types.int;
description = ''
Number of workers.
Recommended to be no more than the number of CPU cores
'';
default = 4;
example = 8;
};
queueSize = mkOption {
type = types.int;
description = "Worker queue size.";
default = 16;
example = 32;
};
tcpMaxBufferedPagesTotal = mkOption {
type = types.int;
description = ''
TCP max total buffered pages.
'';
default = 4096;
example = 8192;
};
tcpMaxBufferedPagesPerConn = mkOption {
type = types.int;
description = ''
TCP max total bufferd pages per connection.
'';
default = 64;
example = 128;
};
tcpTimeout = mkOption {
type = types.str;
description = ''
How long a connection is considered dead when no data is being transferred.
Dead connections are purged from TCP reassembly pools once per minute.
'';
default = "10m";
example = "5m";
};
udpMaxStreams = mkOption {
type = types.int;
description = "UDP max streams.";
default = 4096;
example = 8192;
};
};
};
};
};
}
);
};
rules = mkOption {
default = [ ];
description = ''
Rules passed to OpenGFW. [Example rules](https://gfw.dev/docs/rules)
'';
type = types.listOf (
types.submodule {
options = {
name = mkOption {
description = "Name of the rule.";
example = "block google dns";
type = types.singleLineStr;
};
action = mkOption {
description = ''
Action of the rule. [Supported actions](https://gfw.dev/docs/rules#supported-actions)
'';
default = "allow";
example = "block";
type = types.enum [
"allow"
"block"
"drop"
"modify"
];
};
log = mkOption {
description = "Whether to enable logging for the rule.";
default = true;
example = false;
type = types.bool;
};
expr = mkOption {
description = ''
[Expr Language](https://expr-lang.org/docs/language-definition) expression using [analyzers](https://gfw.dev/docs/analyzers) and [functions](https://gfw.dev/docs/functions).
'';
type = types.str;
example = ''dns != nil && dns.qr && any(dns.questions, {.name endsWith "google.com"})'';
};
modifier = mkOption {
default = null;
description = ''
Modification of specified packets when using the `modify` action. [Available modifiers](https://github.com/apernet/OpenGFW/tree/master/modifier)
'';
type = types.nullOr (
types.submodule {
options = {
name = mkOption {
description = "Name of the modifier.";
type = types.singleLineStr;
example = "dns";
};
args = mkOption {
description = "Arguments passed to the modifier.";
type = types.attrs;
example = {
a = "0.0.0.0";
aaaa = "::";
};
};
};
}
);
};
};
}
);
example = [
{
name = "block v2ex http";
action = "block";
expr = ''string(http?.req?.headers?.host) endsWith "v2ex.com"'';
}
{
name = "block google socks";
action = "block";
expr = ''string(socks?.req?.addr) endsWith "google.com" && socks?.req?.port == 80'';
}
{
name = "v2ex dns poisoning";
action = "modify";
modifier = {
name = "dns";
args = {
a = "0.0.0.0";
aaaa = "::";
};
};
expr = ''dns != nil && dns.qr && any(dns.questions, {.name endsWith "v2ex.com"})'';
}
];
};
};
config =
let
format = pkgs.formats.yaml { };
settings =
if cfg.settings != null then
format.generate "opengfw-config.yaml" cfg.settings
else
cfg.settingsFile;
rules = if cfg.rules != [ ] then format.generate "opengfw-rules.yaml" cfg.rules else cfg.rulesFile;
in
mkIf cfg.enable {
security.wrappers.OpenGFW = {
owner = cfg.user;
group = cfg.user;
capabilities = "cap_net_admin+ep";
source = "${cfg.package}/bin/OpenGFW";
};
systemd.services.opengfw = {
description = "OpenGFW";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
path = with pkgs; [ iptables ];
preStart = ''
${optionalString (rules != null) "ln -sf ${rules} rules.yaml"}
${optionalString (settings != null) "ln -sf ${settings} config.yaml"}
'';
script = ''
${config.security.wrapperDir}/OpenGFW \
-f ${cfg.logFormat} \
-l ${cfg.logLevel} \
${optionalString (cfg.pcapReplay != null) "-p ${cfg.pcapReplay}"} \
-c config.yaml \
rules.yaml
'';
serviceConfig = rec {
WorkingDirectory = cfg.dir;
ExecReload = "${lib.getExe' pkgs.coreutils "kill"} -HUP $MAINPID";
Restart = "always";
User = cfg.user;
StandardOutput = mkIf (cfg.logFile != null) "append:${cfg.logFile}";
StandardError = StandardOutput;
};
};
users = {
groups.${cfg.user} = { };
users.${cfg.user} = {
description = "opengfw user";
isSystemUser = true;
group = cfg.user;
home = cfg.dir;
createHome = true;
homeMode = "750";
};
};
};
meta.maintainers = with lib.maintainers; [ eum3l ];
}
-37
View File
@@ -1,37 +0,0 @@
{
lib,
buildGoModule,
fetchFromGitHub,
}:
buildGoModule (finalAttrs: {
pname = "opengfw";
version = "0.4.1";
src = fetchFromGitHub {
owner = "apernet";
repo = "opengfw";
tag = "v${finalAttrs.version}";
hash = "sha256-6PFfsPfLzzeaImcteX9u/k5pwe3cvSQwT90TCizA3gI=";
};
vendorHash = "sha256-F8jTvgxOhOGVtl6B8u0xAIvjNwVjBtvAhApzjIgykpY=";
env.CGO_ENABLED = 0;
meta = {
mainProgram = "OpenGFW";
description = "Flexible, easy-to-use, open source implementation of GFW on Linux";
longDescription = ''
OpenGFW is your very own DIY Great Firewall of China, available as a flexible,
easy-to-use open source program on Linux. Why let the powers that be have all the fun?
It's time to give power to the people and democratize censorship.
Bring the thrill of cyber-sovereignty right into your home router
and start filtering like a pro - you too can play Big Brother.
'';
homepage = "https://gfw.dev/";
license = lib.licenses.mpl20;
platforms = lib.platforms.linux;
maintainers = with lib.maintainers; [ eum3l ];
};
})
+1
View File
@@ -1499,6 +1499,7 @@ mapAliases {
opencolorio_1 = throw "'opencolorio_1' has been removed. Use opencolorio instead"; # Added 2026-01-03
openconnect_gnutls = throw "'openconnect_gnutls' has been renamed to/replaced by 'openconnect'"; # Converted to throw 2025-10-27
openexr_3 = throw "'openexr_3' has been renamed to/replaced by 'openexr'"; # Converted to throw 2025-10-27
opengfw = throw "'opengfw' has been removed because the upstream repository was deleted"; # Added 2026-03-16
openhmd = throw "'openhmd' has been removed due to being unmaintained upstream"; # Added 2025-11-05
openimageio2 = throw "'openimageio2' has been renamed to/replaced by 'openimageio'"; # Converted to throw 2025-10-27
openjdk23 = throw "OpenJDK 23 was removed as it has reached its end of life"; # Added 2025-11-04