Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions files/recipe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
vars:
home_path: "{{ lookup('env', 'HOME') }}"
packit_service_path: /src
editable_install: "{{ lookup('env', 'DEPLOYMENT') == 'dev' }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] build-time environment

editable_install reads DEPLOYMENT at Ansible execution time. The existing Dockerfile build path does not set this variable, so editable install only works via the new quadlet build path. Likely intentional but undocumented.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] scope-creep

Adding editable_install to the shared Ansible recipe couples the new quadlet workflow to the existing Dockerfile build pipeline. Existing behavior is preserved (DEPLOYMENT unset = non-editable), but the coupling is undocumented.

tasks:
- import_tasks: tasks/common.yaml
- import_tasks: tasks/httpd.yaml
22 changes: 17 additions & 5 deletions files/run_httpd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,30 @@ fi

export PACKIT_SERVICE_CONFIG="${HOME}/.config/packit-service.yaml"
SERVER_NAME=$(sed -nr 's/^server_name: ([^:]+)(:([0-9]+))?$/\1/p' "$PACKIT_SERVICE_CONFIG")
HTTPS_PORT=$(sed -nr 's/^server_name: ([^:]+)(:([0-9]+))?$/\3/p' "$PACKIT_SERVICE_CONFIG")
PORT=$(sed -nr 's/^server_name: ([^:]+)(:([0-9]+))?$/\3/p' "$PACKIT_SERVICE_CONFIG")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] naming-convention

http_flags uses lowercase while all other substantive variables in the file use UPPER_CASE (ATTEMPTS, SERVER_NAME, PORT, PACKIT_SERVICE_CONFIG).

http_flags=(
--http2
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] logic-error

The --http2 flag is unconditionally added to http_flags, including the plain HTTP code path. Apache's mod_http2 requires TLS for h2. Passing --http2 with --port (plain HTTP) may cause mod_wsgi-express to fail to start or silently ignore the flag.

Suggested fix: Move --http2 into the TLS branch (inside the if [[ -f /secrets/privkey.pem ]] block).

if [[ -f /secrets/privkey.pem ]]; then
http_flags+=(
--https-port "${PORT:-8443}"
--ssl-certificate-file /secrets/fullchain.pem
--ssl-certificate-key-file /secrets/privkey.pem

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] fail-open

Silent fallback to plain HTTP (port 8080) when /secrets/privkey.pem is absent. Previously the server always attempted HTTPS and would fail if certificates were missing (fail-closed). This also affects the existing docker-compose deployment path — a misconfiguration could cause unencrypted traffic.

Suggested fix: Add an explicit warning log in the else branch. Consider restricting the HTTP fallback to dev/local deployments only (e.g., gating on DEPLOYMENT env var).

)
else
http_flags+=(
--port "${PORT:-8080}"
)
fi

# See "mod_wsgi-express-3 start-server --help" for details on
# these options, and the configuration documentation of mod_wsgi:
# https://modwsgi.readthedocs.io/en/master/configuration.html
exec mod_wsgi-express-3 start-server \
--access-log \
--log-to-terminal \
--http2 \
--https-port "${HTTPS_PORT:-8443}" \
--ssl-certificate-file /secrets/fullchain.pem \
--ssl-certificate-key-file /secrets/privkey.pem \
"${http_flags[@]}" \
--server-name "${SERVER_NAME}" \
--processes 2 \
--restart-interval 28800 \
Expand Down
1 change: 1 addition & 0 deletions files/tasks/common.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- name: Install packit-service from {{ packit_service_path }}
ansible.builtin.pip:
name: "{{ packit_service_path }}"
editable: "{{ editable_install }}"
- name: Clean all the cache files (especially pip)
ansible.builtin.file:
state: absent
Expand Down
1 change: 1 addition & 0 deletions quadlets/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/local/
46 changes: 46 additions & 0 deletions quadlets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Setting up quadlet environment

> [!CAUTION]
> This setup is still a work in progress

Packit can be deployed as quadlet services. The goal is to make it possible to
simply run

```console
$ systemctl --user daemon-reload
$ systemctl --user start packit-service
```

and be out to the races

## Various environment setups

The quadlets are organized into multiple drop-in configuration folders that get
merged:

- `base`: The main quadlet definitions shared across all environments
- `dev`: Development environment using the current state of the git repo and
that _should_ pick up live edits to the sources
- `prod`: Production environment used/mimicking the current environment
deployed
- `local`: Additional drop-in files setup locally

In order to use these, you can either

1. Copy the drop-in folders into the [quadlet search path]
2. Create a `/etc/systemd/user-environment-generators/10-packit-service`
executable file with content such as

```bash
PACKIT_SERVICE_ROOT=/path/to/packit-service
# Enable dev environment (along with mandatory base drop-ins)
echo "QUADLET_UNIT_DIRS=$PACKIT_SERVICE_ROOT/quadlets/dev:$PACKIT_SERVICE_ROOT/quadlets/base:$QUADLET_UNIT_DIRS"
```

[quadlet search path]: https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html#podman-rootless-unit-search-path

## Additional manual configuration

See the notes in each `base/*/10-*-secrets.conf` drop-in files for additional
setup steps that you are expected to do. Create equivalent drop-in files in
your `local` path.
8 changes: 8 additions & 0 deletions quadlets/base/packit-dashboard.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Unit]
After=packit-service.container
Requires=packit-service.container

[Container]
ContainerName=packit-dashboard
Image=quay.io/packit/dashboard:prod

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] logic-error

The base dashboard container uses Image=quay.io/packit/dashboard:prod while docker-compose.yml uses the :stg tag. The quadlet layered architecture makes :prod as a base default reasonable, but verify this is intentional.

Suggested fix: Verify whether :prod or :stg is the intended tag for the dashboard image.

User=1024
4 changes: 4 additions & 0 deletions quadlets/base/packit-service.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[Container]
ContainerName=packit-service
Image=quay.io/packit/service:prod

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] naming-coherence

Image name quay.io/packit/service:prod differs from docker-compose quay.io/packit/packit-service:dev. The image name itself differs (packit/service vs packit/packit-service).

Suggested fix: Verify whether quay.io/packit/service is the correct image name vs quay.io/packit/packit-service.

User=1024
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Container]
## Secrets are not available in the repo, populate them and mount them
## as follows
#Volume=../../secrets/packit/dev/packit-service.yaml:/home/packit/.config/packit-service.yaml:ro,z
#Volume=../../secrets/packit/dev/fedora.keytab:/secrets/fedora.keytab:ro,z
#Volume=../../secrets/packit/dev/fullchain.pem:/secrets/fullchain.pem:ro,z
#Volume=../../secrets/packit/dev/privkey.pem:/secrets/privkey.pem:ro,z
9 changes: 9 additions & 0 deletions quadlets/base/packit-service.container.d/40-postgres.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
After=postgres.container
Requires=postgres.container

[Container]
Environment=POSTGRESQL_HOST=postgres
Environment=POSTGRESQL_USER=packit
Environment=POSTGRESQL_DATABASE=packit
Network=postgres.network
7 changes: 7 additions & 0 deletions quadlets/base/packit-service.container.d/40-redis.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
After=redis.container
Requires=redis.container

[Container]
Environment=REDIS_SERVICE_HOST=redis
Network=redis.network
4 changes: 4 additions & 0 deletions quadlets/base/postgres.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[Container]
ContainerName=postgres
Image=quay.io/sclorg/postgresql-15-c9s
Network=postgres.network
4 changes: 4 additions & 0 deletions quadlets/base/postgres.container.d/10-postgres-secrets.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[Container]
## Set a POSTGRESQL_PASSWORD environment. Below assumes you created the secret
## manually via `podman secret create`
#Secret=postgres-password,type=env,target=POSTGRESQL_PASSWORD
3 changes: 3 additions & 0 deletions quadlets/base/postgres.container.d/50-packit-service.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Container]
Environment=POSTGRESQL_USER=packit
Environment=POSTGRESQL_DATABASE=packit
1 change: 1 addition & 0 deletions quadlets/base/postgres.network
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Network]
5 changes: 5 additions & 0 deletions quadlets/base/redis.container
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Container]
ContainerName=redis
Image=quay.io/sclorg/redis-6-c9s
User=1024
Network=redis.network
1 change: 1 addition & 0 deletions quadlets/base/redis.network
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Network]
2 changes: 2 additions & 0 deletions quadlets/dev/packit-dashboard.container.d/60-dev.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Container]
Environment=DEPLOYMENT=dev
6 changes: 6 additions & 0 deletions quadlets/dev/packit-service.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[Build]
ImageTag=localhost/packit-service:dev

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] naming-convention

ImageTag=localhost/packit-service:dev uses localhost/ prefix. This is standard Podman practice for locally-built images but differs from the quay.io convention used elsewhere in the project.

SetWorkingDirectory=../../
File=files/docker/Dockerfile
Environment=SOURCE_BRANCH=main

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] api-contract

Uses Environment=SOURCE_BRANCH=main in the [Build] section. While Environment= maps to podman build --env and makes the variable available during RUN instructions, it is semantically intended for build-time environment, not for satisfying Dockerfile ARG declarations. Consider using PodmanArgs=--build-arg SOURCE_BRANCH=main for clarity.

Suggested fix: Change Environment=SOURCE_BRANCH=main to PodmanArgs=--build-arg SOURCE_BRANCH=main in quadlets/dev/packit-service.build.

Environment=DEPLOYMENT=dev
5 changes: 5 additions & 0 deletions quadlets/dev/packit-service.container.d/60-dev.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Container]
Environment=DEPLOYMENT=dev
Image=packit-service.build
Volume=../../packit_service:/src/packit_service:ro,z

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] edge-case

Volume directives use relative paths (../../packit_service and ../../alembic). Relative paths in systemd units resolve relative to the service WorkingDirectory, not the unit file location. Without an explicit WorkingDirectory, these may not resolve to the intended repo root paths.

Suggested fix: Test that the volume mounts resolve correctly. Consider setting WorkingDirectory in the [Service] section or using absolute paths.

Volume=../../alembic:/src/alembic:rw,z
2 changes: 2 additions & 0 deletions quadlets/prod/packit-dashboard.container.d/60-prod.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Container]
Environment=DEPLOYMENT=prod
2 changes: 2 additions & 0 deletions quadlets/prod/packit-service.container.d/60-prod.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[Container]
Environment=DEPLOYMENT=prod
Loading