AUR
Publish to the Arch User Repository
Anodizer generates Arch Linux PKGBUILD and .SRCINFO files and pushes them to the Arch User Repository via SSH. Two package types are supported:
- Binary packages (
-bin) install prebuilt binaries from your release archives. Configured viapublish.aur. - Source packages build from source using
cargo build. Configured viapublish.aur_source(per-crate) or the top-levelaur_sourcesarray (project-wide).
Classification
| Package type | Group | Required (default) | Rollback | Token scope |
|---|---|---|---|---|
| our-AUR-repos (binary / source) | Manager | false | git revert + push | AUR_SSH_KEY write |
| upstream-AUR (force-push) | Submitter | false | none | AUR_SSH_KEY write |
See Release resilience for the full classification table and the Submitter gate semantics.
The required: field
Default: false for both package types — an AUR push failure is logged but does not fail the release.
Set required: true to make the release exit non-zero if this publisher fails:
crates:
- name: myapp
publish:
aur:
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git"
required: true
See Publish overview — the required: field for the full semantics.
Minimal config
Pick one or both. Binary packages distribute prebuilt artifacts; source packages build via cargo.
crates:
- name: myapp
publish:
aur: # binary package — uses release archive
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git"
aur_source: # source package — builds via cargo
git_url: "ssh://aur@aur.archlinux.org/myapp.git"Full config reference
Binary package (publish.aur)
crates:
- name: myapp
publish:
aur:
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git" # required
name: myapp-bin # optional; default: <crate>-bin
description: "" # optional
homepage: "" # optional
license: "" # optional; SPDX identifier
depends: [] # optional; runtime deps
optdepends: [] # optional
conflicts: [] # optional; default: [<base_name>]
provides: [] # optional; default: [<base_name>]
replaces: [] # optional
backup: [] # optional; config files to preserve
maintainers: [] # optional
contributors: [] # optional
rel: "1" # optional; pkgrel
ids: [] # optional; filter by build IDs
amd64_variant: v1 # optional; v1 | v2 | v3 | v4
url_template: "" # optional; override download URL
package: "" # optional; custom package() body
install: "" # optional; .install file content
directory: "" # optional; subdirectory in AUR repo
private_key: "" # optional; SSH key path (template)
git_ssh_command: "" # optional; custom SSH invocation
commit_author:
name: ""
email: ""
commit_msg_template: "" # optional
skip_upload: false # optional; true | false | "auto"
disable: false # optionalSource package (publish.aur_source)
crates:
- name: myapp
publish:
aur_source:
git_url: "ssh://aur@aur.archlinux.org/myapp.git" # optional; write to dist/ if omitted
name: myapp # optional; default: crate name
description: "" # optional
homepage: "" # optional
license: MIT # optional
maintainers: [] # optional
contributors: [] # optional
provides: [] # optional
conflicts: [] # optional
depends: [] # optional
optdepends: [] # optional
makedepends: ["rust", "cargo"] # optional
backup: [] # optional
rel: "1" # optional
prepare: "" # optional; custom prepare() body
build: "" # optional; default: cargo build --release --locked
package: "" # optional; custom package() body
url_template: "" # optional; source archive URL
git_ssh_command: "" # optional
private_key: "" # optional
directory: "" # optional
skip_upload: false # optional; "auto" skips prereleases
commit_author:
name: ""
email: ""
commit_msg_template: "" # optional
arches: [] # optional; architecture filter
disable: false # optionalAuthentication
AUR publishing requires SSH access to the AUR git server. See SSH key setup below for setup instructions.
| Config field | Env var | Description |
|---|---|---|
private_key | — | Path to SSH private key file |
git_ssh_command | — | Override the full SSH invocation |
| — | AUR_SSH_KEY | SSH key content (used via private_key: "{{ Env.AUR_SSH_KEY }}") |
Common gotchas
- Version string hyphens: AUR
pkgverdoes not allow hyphens. Anodizer replaces hyphens with underscores (e.g.1.0.0-rc1→1.0.0_rc1). Ensure your PKGBUILD validators account for this. .SRCINFOgenerated automatically: anodizer generates.SRCINFOalongside the PKGBUILD without runningmakepkg --printsrcinfo. If you maintain additional AUR metadata outside anodizer, ensure the committed.SRCINFOstays in sync.- No
git_url: ifgit_urlis omitted for source packages, PKGBUILD files are generated indist/but not pushed. Useful for local inspection before AUR submission. - Force-push upstream AUR: upstream AUR push is a force-push that overwrites the branch; it is classified as Submitter because it cannot be rolled back programmatically.
Binary packages (publish.aur)
Binary packages download a prebuilt archive from your release and install the binary. The package name defaults to <crate>-bin following AUR convention.
Minimal config
crates:
- name: myapp
publish:
aur:
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git"Config fields
| Field | Type | Default | Description |
|---|---|---|---|
name | string | <crate>-bin | Override the AUR package name |
git_url | string | required | AUR SSH git URL (e.g. ssh://aur@aur.archlinux.org/<pkg>.git) |
description | string | Cargo [package].description | Short description for pkgdesc. Derived from Cargo.toml (falls back to crate name). |
homepage | string | Cargo [package].homepage | Project homepage URL. Resolves homepage: → crate metadata homepage → the derived release.github owner/name URL |
license | string | Cargo [package].license | SPDX license identifier (e.g. MIT, Apache-2.0). Derived from Cargo.toml; set to override. |
depends | string[] | [] | Runtime dependencies (e.g. glibc) |
optdepends | string[] | [] | Optional dependencies with descriptions (e.g. fzf: fuzzy finder support) |
conflicts | string[] | [<base_name>] | Packages this conflicts with. Defaults to the package name without -bin |
provides | string[] | [<base_name>] | Virtual packages provided. Defaults to the package name without -bin |
replaces | string[] | [] | Packages this replaces (for upgrade paths from old names) |
backup | string[] | [] | Config files to preserve on upgrade (paths relative to /) |
maintainers | string[] | [] | Maintainer lines in PKGBUILD (e.g. Name <email>) |
contributors | string[] | [] | Contributor comment lines in PKGBUILD |
rel | string | "1" | Package release number (pkgrel) |
ids | string[] | all | Build IDs filter: only include artifacts whose id is in this list |
amd64_variant | enum | "v1" | amd64 microarchitecture variant filter — exactly one of v1, v2, v3, v4 (any other value is rejected when the config is parsed) |
url_template | string | release URL | Custom download URL template (overrides artifact URLs) |
package | string | auto | Custom package() function body for PKGBUILD |
install | string | none | Content for a .install file (post-install/pre-remove hooks) |
directory | string | repo root | Subdirectory in the AUR git repo for committed files. Supports templates |
private_key | string | none | Path to SSH private key file |
git_ssh_command | string | none | Custom SSH command for git operations |
commit_author | object | none | Override commit author (name, email) |
commit_msg_template | string | Update to <version> | Custom commit message template |
skip_upload | bool/string | false | Skip publishing. true always skips; "auto" skips for prereleases |
disable | bool/string | false | Disable this config entirely. Accepts a template string for conditional disable |
Full example
crates:
- name: myapp
publish:
aur:
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git"
name: myapp-bin
description: "A fast CLI tool"
homepage: "https://github.com/myorg/myapp"
license: MIT
depends:
- glibc
optdepends:
- "bash-completion: shell completions"
maintainers:
- "Jane Doe <jane@example.com>"
private_key: "{{ Env.AUR_SSH_KEY }}"
skip_upload: autoGenerated PKGBUILD
Anodizer generates a PKGBUILD with:
- Per-architecture source arrays (
source_x86_64,source_aarch64, etc.) with SHA-256 checksums - Automatic architecture detection from your Linux build artifacts (
x86_64,aarch64,i686,armv7h) - Version strings with hyphens replaced by underscores (AUR
pkgverrequirement) - Download URLs with the version substituted as
${pkgver}for AUR compatibility - A
.SRCINFOfile generated alongside the PKGBUILD (nomakepkg --printsrcinfodependency)
The default package() function installs the binary to /usr/bin:
package() {
install -Dm755 "$srcdir/myapp" "$pkgdir/usr/bin/myapp"
}
Override this with the package field when your archive has a different structure.
Source packages (publish.aur_source)
Source packages download a source tarball and build from source using cargo build. The package name does not have a -bin suffix.
Minimal config
crates:
- name: myapp
publish:
aur_source:
git_url: "ssh://aur@aur.archlinux.org/myapp.git"Config fields
| Field | Type | Default | Description |
|---|---|---|---|
name | string | crate name | Override the AUR package name (no -bin suffix) |
git_url | string | none | AUR SSH git URL. If omitted, files are written to dist/ but not pushed |
description | string | crate name | Short description for pkgdesc |
homepage | string | none | Project homepage URL |
license | string | MIT | SPDX license identifier |
depends | string[] | [] | Runtime dependencies |
makedepends | string[] | ["rust", "cargo"] | Build-time dependencies |
optdepends | string[] | [] | Optional dependencies |
conflicts | string[] | [<name>-bin] | Packages this conflicts with. Defaults to <name>-bin |
provides | string[] | [<name>] | Virtual packages provided |
backup | string[] | [] | Config files to preserve on upgrade |
maintainers | string[] | [] | Maintainer lines in PKGBUILD |
contributors | string[] | [] | Contributor comment lines |
rel | string | "1" | Package release number |
url_template | string | GitHub archive URL | Custom source tarball URL template |
prepare | string | none | Custom prepare() function body |
build | string | cargo build --release --locked | Custom build() function body |
package | string | install -Dm755 ... | Custom package() function body |
directory | string | repo root | Subdirectory in the AUR git repo. Supports templates |
private_key | string | none | Path to SSH private key file |
git_ssh_command | string | none | Custom SSH command |
commit_author | object | none | Override commit author |
commit_msg_template | string | Update to <version> | Custom commit message template |
ids | string[] | all | Build IDs filter |
arches | string[] | auto | Explicit architecture list |
skip_upload | bool/string | false | Skip publishing. true always skips; "auto" skips for prereleases |
disable | bool/string | false | Disable this config entirely |
Full example
crates:
- name: myapp
publish:
aur_source:
git_url: "ssh://aur@aur.archlinux.org/myapp.git"
name: myapp
description: "A fast CLI tool"
homepage: "https://github.com/myorg/myapp"
license: MIT
depends:
- glibc
makedepends:
- rust
- cargo
maintainers:
- "Jane Doe <jane@example.com>"
private_key: "{{ Env.AUR_SSH_KEY }}"
skip_upload: autoGenerated source PKGBUILD
The default source PKGBUILD downloads the GitHub release source tarball and builds with Cargo:
build() {
cd "$srcdir/myapp-$pkgver"
cargo build --release --locked
}
package() {
cd "$srcdir/myapp-$pkgver"
install -Dm755 "target/release/myapp" "$pkgdir/usr/bin/myapp"
}
If no url_template is set, the source URL defaults to:
https://github.com/<owner>/<project>/archive/refs/tags/<tag>.tar.gz
The owner and project are derived from GitURL and ProjectName template variables.
Top-level aur_sources
For project-wide source packages not tied to a specific crate, use the top-level aur_sources array. This follows the same schema as publish.aur_source and accepts multiple entries:
aur_sources:
- name: myapp
git_url: "ssh://aur@aur.archlinux.org/myapp.git"
description: "A fast CLI tool"
license: MIT
makedepends:
- rust
- cargo
- name: myapp-git
git_url: "ssh://aur@aur.archlinux.org/myapp-git.git"
description: "A fast CLI tool (git version)"
license: MIT
Each entry generates its own PKGBUILD and .SRCINFO, written to dist/aur_source/<name>/ and optionally pushed to the configured AUR git URL.
One package name per entry
The AUR keys a package on its name, so two entries that render the same name: would push one PKGBUILD over the other and the second config would ship silently. The pre-publish guard renders every publish.aur, publish.aur_source and aur_sources[] entry (each in its own crate's scope) and fails the release before any push when two or more of them name one package on one push remote. Every entry in the group is named in a single finding:
$ anodizer release --snapshot
...
Error publisher artifact schema validation failed:
aur: field 'pkgname' — package name 'myapp' is rendered by both crate 'cli' (publish.aur) and aur_sources[0] — two entries sharing one AUR package push one PKGBUILD over the other; give each entry its own `name:`
An entry that is skipped (skip, skip_upload, a falsy if:) pushes nothing and claims no name.
The remote is the entry's git_url:, or ssh://aur@aur.archlinux.org/<name>.git when none is written. Two entries that render one name and push it to two different remotes are two packages, and both are accepted.
SSH key setup
AUR publishing requires SSH access. To configure this:
-
Generate an SSH key (if you do not already have one for AUR):
ssh-keygen -t ed25519 -f ~/.ssh/aur -N "" -
Add the public key to your AUR account at https://aur.archlinux.org/account under "SSH Public Key".
-
Reference the private key in your config:
publish: aur: git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git" private_key: "{{ Env.AUR_SSH_KEY }}" -
In CI, store the private key as a secret and expose it as an environment variable:
# GitHub Actions example env: AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }}
Alternatively, use git_ssh_command for full control over the SSH invocation:
publish:
aur:
git_url: "ssh://aur@aur.archlinux.org/myapp-bin.git"
git_ssh_command: "ssh -i /path/to/key -o StrictHostKeyChecking=no"
If neither private_key nor git_ssh_command is set, Anodizer uses the system default SSH configuration (e.g. ~/.ssh/config, ssh-agent).
skip_upload behavior
The skip_upload field controls whether Anodizer pushes to the AUR git repo:
| Value | Behavior |
|---|---|
false (default) | Always publish |
true | Never publish (PKGBUILD is still generated locally) |
"auto" | Skip publishing for prerelease versions (e.g. 1.0.0-rc1) |
| template string | Evaluated as a template; skips when the result is "true" |
The disable field works similarly but skips the entire stage, including PKGBUILD generation.
Artifact eligibility
anodizer packages only the Linux archives for AUR; every non-Linux target is
excluded from the generated PKGBUILD. If a configured AUR build produces no
Linux archive, anodizer fails the release (aur: no linux archives matched)
rather than emitting an empty PKGBUILD. See
Artifact eligibility for the
full rule.