Skip to main content

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 via publish.aur.
  • Source packages build from source using cargo build. Configured via publish.aur_source (per-crate) or the top-level aur_sources array (project-wide).

Classification

Package typeGroupRequired (default)RollbackToken scope
our-AUR-repos (binary / source)Managerfalsegit revert + pushAUR_SSH_KEY write
upstream-AUR (force-push)SubmitterfalsenoneAUR_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               # optional

Source 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               # optional

Authentication

AUR publishing requires SSH access to the AUR git server. See SSH key setup below for setup instructions.

Config fieldEnv varDescription
private_keyPath to SSH private key file
git_ssh_commandOverride the full SSH invocation
AUR_SSH_KEYSSH key content (used via private_key: "{{ Env.AUR_SSH_KEY }}")

Common gotchas

  • Version string hyphens: AUR pkgver does not allow hyphens. Anodizer replaces hyphens with underscores (e.g. 1.0.0-rc11.0.0_rc1). Ensure your PKGBUILD validators account for this.
  • .SRCINFO generated automatically: anodizer generates .SRCINFO alongside the PKGBUILD without running makepkg --printsrcinfo. If you maintain additional AUR metadata outside anodizer, ensure the committed .SRCINFO stays in sync.
  • No git_url: if git_url is omitted for source packages, PKGBUILD files are generated in dist/ 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

FieldTypeDefaultDescription
namestring<crate>-binOverride the AUR package name
git_urlstringrequiredAUR SSH git URL (e.g. ssh://aur@aur.archlinux.org/<pkg>.git)
descriptionstringCargo [package].descriptionShort description for pkgdesc. Derived from Cargo.toml (falls back to crate name).
homepagestringCargo [package].homepageProject homepage URL. Resolves homepage: → crate metadata homepage → the derived release.github owner/name URL
licensestringCargo [package].licenseSPDX license identifier (e.g. MIT, Apache-2.0). Derived from Cargo.toml; set to override.
dependsstring[][]Runtime dependencies (e.g. glibc)
optdependsstring[][]Optional dependencies with descriptions (e.g. fzf: fuzzy finder support)
conflictsstring[][<base_name>]Packages this conflicts with. Defaults to the package name without -bin
providesstring[][<base_name>]Virtual packages provided. Defaults to the package name without -bin
replacesstring[][]Packages this replaces (for upgrade paths from old names)
backupstring[][]Config files to preserve on upgrade (paths relative to /)
maintainersstring[][]Maintainer lines in PKGBUILD (e.g. Name <email>)
contributorsstring[][]Contributor comment lines in PKGBUILD
relstring"1"Package release number (pkgrel)
idsstring[]allBuild IDs filter: only include artifacts whose id is in this list
amd64_variantstring"v1"amd64 microarchitecture variant filter (v1, v2, v3, v4)
url_templatestringrelease URLCustom download URL template (overrides artifact URLs)
packagestringautoCustom package() function body for PKGBUILD
installstringnoneContent for a .install file (post-install/pre-remove hooks)
directorystringrepo rootSubdirectory in the AUR git repo for committed files. Supports templates
private_keystringnonePath to SSH private key file
git_ssh_commandstringnoneCustom SSH command for git operations
commit_authorobjectnoneOverride commit author (name, email)
commit_msg_templatestringUpdate to <version>Custom commit message template
skip_uploadbool/stringfalseSkip publishing. true always skips; "auto" skips for prereleases
disablebool/stringfalseDisable 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: auto

Generated 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 pkgver requirement)
  • Download URLs with the version substituted as ${pkgver} for AUR compatibility
  • A .SRCINFO file generated alongside the PKGBUILD (no makepkg --printsrcinfo dependency)

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

FieldTypeDefaultDescription
namestringcrate nameOverride the AUR package name (no -bin suffix)
git_urlstringnoneAUR SSH git URL. If omitted, files are written to dist/ but not pushed
descriptionstringcrate nameShort description for pkgdesc
homepagestringnoneProject homepage URL
licensestringMITSPDX license identifier
dependsstring[][]Runtime dependencies
makedependsstring[]["rust", "cargo"]Build-time dependencies
optdependsstring[][]Optional dependencies
conflictsstring[][<name>-bin]Packages this conflicts with. Defaults to <name>-bin
providesstring[][<name>]Virtual packages provided
backupstring[][]Config files to preserve on upgrade
maintainersstring[][]Maintainer lines in PKGBUILD
contributorsstring[][]Contributor comment lines
relstring"1"Package release number
url_templatestringGitHub archive URLCustom source tarball URL template
preparestringnoneCustom prepare() function body
buildstringcargo build --release --lockedCustom build() function body
packagestringinstall -Dm755 ...Custom package() function body
directorystringrepo rootSubdirectory in the AUR git repo. Supports templates
private_keystringnonePath to SSH private key file
git_ssh_commandstringnoneCustom SSH command
commit_authorobjectnoneOverride commit author
commit_msg_templatestringUpdate to <version>Custom commit message template
idsstring[]allBuild IDs filter
archesstring[]autoExplicit architecture list
skip_uploadbool/stringfalseSkip publishing. true always skips; "auto" skips for prereleases
disablebool/stringfalseDisable 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: auto

Generated 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.

SSH key setup

AUR publishing requires SSH access. To configure this:

  1. Generate an SSH key (if you do not already have one for AUR):

    ssh-keygen -t ed25519 -f ~/.ssh/aur -N ""
  2. Add the public key to your AUR account at https://aur.archlinux.org/account under "SSH Public Key".

  3. 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 }}"
  4. 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:

ValueBehavior
false (default)Always publish
trueNever publish (PKGBUILD is still generated locally)
"auto"Skip publishing for prerelease versions (e.g. 1.0.0-rc1)
template stringEvaluated as a template; skips when the result is "true"

The disable field works similarly but skips the entire stage, including PKGBUILD generation.