Capirca turns one policy file into ACLs for every firewall you have
Multi-platform ACL generation system
At a glance
- What is it?
- Capirca is Google's open source system for generating network access control lists across platforms from shared definitions of networks and services and a high-level policy file, driven by the aclgen command. It replaces a pile of vendor-specific rule sets with one language, and its cost is a generator per platform plus the platform specific keywords you may have to avoid.
- Who is it for?
- Adopt Capirca when you operate more than one firewall platform and the same access rules are being retyped in each vendor's format, because the objects and terms are written once and the generators handle the rest.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One language in front of many firewall dialects
Capirca is designed to use common definitions of networks, services and high-level policy files to produce network access control lists for various platforms. It was developed by Google for internal use and is now open source.
The project has two parts, and knowing them makes the rest obvious. There is the capirca Python package, and there is the aclgen command line tool, which is the only console script the package installs.
The problem being solved is a familiar one in any organisation with more than one firewall vendor. The rule set is the same, the semantics are nearly the same, and the configuration syntax is not the same at all. Capirca puts a single language in front of that, so the network engineers write terms once and the tool emits the vendor specific form for each platform.
That is also why the generator, rather than the language, is the interesting part of the design. The same policy file can carry a header that targets several firewall platforms at once, and the tool then runs a generator for each of them.
The licence is Apache-2.0, the language is Python, and the project was written at Google, so the code style and the object model carry that origin. The last push to the default branch was on 2026-10-06, and the repository is not archived.
The three step workflow: objects, policy, generation
The README describes the typical usage workflow in three steps, and the repository layout mirrors it.
Step one is to create object definitions containing network and service definitions. Step two is to create an access control policy that defines the desired state of access control and references those object definitions together with the desired firewall platforms. Step three is to generate the ACL configurations by running aclgen, referencing the policy and the objects, which triggers a generator for each of the firewall platforms.
The object definitions live in a directory the README calls def, and the file extension decides the type. A network object file has the .net extension and holds network objects such as IP networks and hosts, and a service object file has the .svc extension and holds services, which are ports and protocols.
Each definition is a token, an equal sign, a definition and an optional comment:
GUEST_NET = 10.10.10.0/24 # guest network rangeThe policy files live under policies, and the tool searches recursively for .pol files, so a directory of policies is picked up as a whole rather than file by file. A .pol file may also pull in policy definitions from outside its own directory with the include directive, which is how shared policies are reused across teams.
That separation, objects in one place and policy in another, is the core of the design. A network range is defined once and every term that refers to it stays consistent across every generated ACL.
Nesting is allowed, but only within one type
The object files have a small, strict grammar, and the README is explicit about the one rule that trips people up: nesting of tokens is permitted only when both tokens are of the same type. Referencing a network object from a service object is not allowed, and neither is the reverse.
Networks can refer to networks, which is how shared ranges are composed:
RFC1918 = 10.0.0.0/8 # non-public
172.16.0.0/12 # non-public
192.168.0.0/16 # non-public
INTERNAL = RFC1918Services compose in the same way, and a definition can list several tokens:
HTTP = 80/tcp # common web
HTTPS = 443/tcp # SSL web
HTTP_8080 = 8080/tcp # web on non-standard port
WEB_SERVICES = HTTP HTTP_8080 HTTPS # all our web services
DB_SERVICES = 3306/tcp # allow db access
HTTPS # and SSL accessA network object may mix address families, and the README gives an example with both an IPv4 and an IPv6 range in one definition:
LOOPBACK = 127.0.0.1/32 # loopback in IPv4
::1/128 # loopback in IPv6
LINKLOCAL = FE80::/10 # IPv6 link local address
NYC_NETWORK = 172.16.1.0/24 # NYC IPv4
2620:0:10A1::/48 # NYC IPv6The type rule is a design decision rather than a limitation of the parser. Keeping networks and services in separate namespaces means a term can be checked for consistency without ambiguity, and it stops a service name from ever being usable as an address.
The policy file: headers, terms and the required keywords
A policy file has specific sections, and the header section tells Capirca how to generate the output configuration.
The header defines the target firewall platforms, which decides which ACL generator to use, and passes additional arguments to the generator responsible for that platform. A single header may have many targets within a section, and that results in multiple outputs being generated for that policy.
The term sections define the access control rules within an ACL. A term contains keywords followed by an object token for rule evaluation and a policy decision, and it specifies the network flow metadata for ACL matching: addresses, ports, protocols and the action.
Keywords are split into two classes, and the distinction is the one to internalise. The required class must be supported by all output policy generators. The optional class is available in a subset of the generators and is intended to give extra flexibility when developing policies for a specific target platform.
The required keyword shown in the README is the action, with the values accept, deny, reject, next and reject-with-tcp-rst. The meaning of next is the one to check in your platform, since it depends on how the generator expresses rule ordering, and reject-with-tcp-rst is a behavioural distinction between a silent drop and a reset.
Since optional keywords are generator specific, a policy that uses them is no longer portable across platforms. That is the trade the two keyword classes encode, and it is why the optional list is the part to read before you write a policy for a fleet of firewalls.
Installing capirca and running aclgen
The install path is ordinary Python packaging, and the dependencies are small.
pip install -r requirements.txtThe requirements file lists absl-py, ply, PyYAML, six with a version floor of 1.12.0, and typing_extensions. ply is the parser generator that implements the policy language, and PyYAML handles the YAML files.
Then the package itself is installed from the checkout, and the setup.py reads the version from the VERSION file in the repository root rather than hard coding it, and registers a single console script:
entry_points={
'console_scripts': ['aclgen = capirca.aclgen:EntryPoint'],
},The package exposes three packages, capirca, capirca.lib and capirca.utils, and the classifiers describe it as a production/stable package under the Apache Software License, operating system independent, for Python 3 and listed as Python 3.6.
A Dockerfile is provided for containerised runs. It is built on python:3.6-alpine, installs the requirements, copies the source, installs the package, sets the working directory to /data and declares aclgen as the entry point, which means a container run is aclgen with your policy directory mounted.
The repository also carries the rest of a working setup: a def directory for object definitions, a policies directory, tests, a doc folder, a tools folder, an aclcheck_cmdline.py for checking policies, a policy.bzl file for Bazel users, a make_dist.sh, a dev-install script, a pre-commit configuration and a Travis CI file.
The release gap and the per-platform generator surface
Two practical limits are visible in the repository state.
The first is the release gap. The most recent tags are v2.0.7 on 2023-01-17, v2.0.8 on 2023-01-28 and v2.0.9 on 2023-02-17, while the last push to the master branch was on 2026-10-06. The project is still receiving commits, but there is no tagged release from the last three and a half years. If you depend on it, you are depending on a branch rather than on a published version, and the version inside the VERSION file is what tells you what you are running.
The second is the generator surface. Every platform needs a generator, and each generator implements the required keywords plus whichever optional ones it can express. A policy that is portable across all your firewalls has to stick to the required keywords, which is a real constraint when a vendor offers a feature Capirca cannot yet render.
There is a related trap in the object model. When a network object is referenced by more than one term, the generator has to decide how to render it, and whether the platform supports overlapping or duplicated entries can change the output. The README does not document the disambiguation rules for every generator, so the sensible check is to diff the generated configuration against what your firewall currently runs before you trust it in production.
The aclcheck_cmdline.py entry point and the tests directory exist for that reason, and running them against your own policies is the cheapest way to find out whether the generator agrees with your existing rule set.
The alternative is a rule set per vendor
There is a second way to run a fleet of firewalls, and it is what most organisations do before they adopt a generator.
That approach is to keep one rule set per platform. Someone translates each rule into the vendor's syntax, often by hand, and the copies drift apart until nobody is sure which firewall has which rule. The advantage is honest, and it is the reason the approach persists. There is no new tool to install, no intermediate language to learn, and any feature the vendor supports is available immediately.
Capirca inverts that. The rules are written once in terms and objects, and the vendor syntax becomes an output artefact rather than a source of truth. The gain is consistency, and it grows with the number of platforms and the size of the rule set. The cost is that the language is now a dependency of your change process, that a rule using a vendor specific feature may not be expressible in a portable way, and that you have to trust a generator you did not write for the parts of the configuration that are not simple allow and deny rules.
There is a third option worth naming for smaller estates. If you run one platform, or your rule set is small and mostly hand written, Capirca adds a layer without removing duplication, because there is no duplication to remove. In that case the tool is mostly overhead, and the deciding question is not how good the generators are but how many rule copies you are currently maintaining by hand.
Editorial conclusion
Adopt Capirca when you operate more than one firewall platform and the same access rules are being retyped in each vendor's format, because the objects and terms are written once and the generators handle the rest. Do not adopt it if you run a single platform, if the rules you need rely on vendor specific features, since those fall under optional keywords that only some generators implement, or if you want a released package, because the latest tag on GitHub is from 2023 even though the branch is still receiving commits. Before you start, check the generator list for the platforms you operate and read the optional keyword table, then run aclgen against one policy and diff the output against your current rule set.
Frequently asked questions
What is capirca and who uses it?
Capirca is a multi-platform ACL generation system developed by Google for internal use and now open source. It consists of the capirca Python package and the aclgen command line tool, and it was written at Google with an Apache 2.0 licence.
How do I install capirca?
Run pip install -r requirements.txt for absl-py, ply, PyYAML, six and typing_extensions, then install the package from the checkout, which registers the aclgen console script through the entry point in setup.py. A Dockerfile on python:3.6-alpine is also included for containerised runs.
Which files does capirca need for a policy?
Network objects live in .net files and service objects in .svc files under the def directory, and the policy itself lives in .pol files under policies, which the tool searches recursively. A .pol file can also pull in other policy files with the include directive.
Which keywords work on every capirca generator?
The required class, which every output generator must support, and the README shows the action keyword with accept, deny, reject, next and reject-with-tcp-rst. Other keywords are optional and available only in a subset of the generators, so a portable policy should stick to the required ones.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/google-capirca)Was this useful?