Upload your first package¶
What you'll learn:
- How to build a minimal
.debpackage from scratch - How to upload it to Repod and watch the pipeline run
- How to install it on a client machine with
apt install
Time: ~15 minutes
Prerequisites: Repod running locally (see Getting Started), curl, jq, dpkg-deb
Step 1 — Build a minimal .deb package¶
Let's create a simple package that installs a shell script.
# Create the package directory tree
mkdir -p ~/hello-repod/DEBIAN
mkdir -p ~/hello-repod/usr/local/bin
# The script our package will install
cat > ~/hello-repod/usr/local/bin/hello-repod << 'EOF'
#!/bin/bash
echo "Hello from Repod! Package management that actually works."
EOF
chmod +x ~/hello-repod/usr/local/bin/hello-repod
# The control file — package metadata
cat > ~/hello-repod/DEBIAN/control << 'EOF'
Package: hello-repod
Version: 1.0.0
Architecture: all
Maintainer: Your Name <[email protected]>
Description: A demo package for Repod
This package was created to demonstrate the Repod upload pipeline.
EOF
# Build the .deb
dpkg-deb --build ~/hello-repod ~/hello-repod_1.0.0_all.deb
You should see:
Step 2 — Get an authentication token¶
Navigate to http://localhost:3003 and sign in. The web UI handles authentication automatically — continue to Step 3 in the browser.
Step 3 — Upload the package¶
curl -X POST http://localhost:8000/upload/ \
-H "Authorization: Bearer $TOKEN" \
-F "file=@$HOME/hello-repod_1.0.0_all.deb" \
-F "distribution=jammy"
Response:
- Click Upload in the left sidebar
- Drag
hello-repod_1.0.0_all.debinto the upload zone - Select jammy from the distribution dropdown
- Click Upload and watch the pipeline steps appear in real time
The pipeline runs 7 checks automatically. A clean package like this one passes everything in a few seconds.
What if a CVE is found?
If Grype detects a vulnerability (depending on your policy), the package enters pending_review status. It won't be published until a user with the admin role reviews and approves it. See the CVE review workflow.
Step 4 — Verify it's in the repository¶
# Check the API
curl -s -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/packages/?q=hello-repod" | jq .
# Check the APT index directly
curl -s "http://localhost/repos/dists/jammy/main/binary-all/Packages" \
| grep -A5 "Package: hello-repod"
Step 5 — Install from a client machine¶
On any machine that should use your repository (can be the same machine for this tutorial):
# 1. Trust the repository's GPG key
curl -sL http://localhost/repos/dists/jammy/Release.gpg \
| gpg --dearmor \
| sudo tee /etc/apt/trusted.gpg.d/repod.gpg > /dev/null
# 2. Add the repository source
echo "deb http://localhost/repos jammy main" \
| sudo tee /etc/apt/sources.list.d/repod.list
# 3. Update and install
sudo apt update
sudo apt install hello-repod
# 4. Run it!
hello-repod
Expected output:
Troubleshooting¶
Upload fails with 'invalid distribution'
The distribution name must match one configured in your repository. Common names: focal, jammy, noble, bookworm, bullseye. Check Settings → APT Sources in the web UI for available distributions.
Pipeline says 'CVE found — pending review'
Your CVE policy is set to review for the detected severity. Go to Security → Review Queue in the web UI. You'll see the CVE details and can approve or reject the package.
apt update fails with 'NO_PUBKEY'
The GPG key wasn't imported correctly. Re-run Step 5's first command. Make sure the URL is reachable from the client machine (replace localhost with your server's IP if on a different machine).
Next steps¶
- Set up CI/CD publishing → — automate this with GitHub Actions or GitLab CI
- API Reference → — all upload options documented
- Security pipeline explained → — understand each pipeline step