143 lines
13 KiB
Markdown
143 lines
13 KiB
Markdown
# Artifactview
|
|
|
|
View CI build artifacts from Forgejo/Github using your web browser.
|
|
|
|
Forgejo and GitHub's CI systems allow you to upload files and directories as
|
|
[artifacts](https://github.com/actions/upload-artifact). These can be downloaded as zip
|
|
files. However there is no simple way to view individual files of an artifact.
|
|
|
|
Artifactview is a small web application that fetches these CI artifacts and displays
|
|
their contents.
|
|
|
|
It offers full support for single page applications and custom 404 error pages.
|
|
Single-page applications require a file named `200.html` placed in the root directory,
|
|
which will be served in case no file exists for the requested path. A custom 404 error
|
|
page is defined using a file named `404.html` in the root directory.
|
|
|
|
Artifactview displays a file listing if there is no `index.html` or fallback page
|
|
present, so you can browse artifacts that dont contain websites.
|
|
|
|
![Artifact file listing](resources/screenshotFiles.png)
|
|
|
|
## How to use
|
|
|
|
Open a Github/Gitea/Forgejo actions run with artifacts and paste its URL into the input
|
|
box on the main page. You can also pass the run URL with the `?url=` parameter.
|
|
|
|
Artifactview will show you a selection page where you will be able to choose the
|
|
artifact you want to browse.
|
|
|
|
## Setup
|
|
|
|
You can run artifactview using the docker image provided under
|
|
`thetadev256/artifactview:latest` or bare-metal using the provided binaries.
|
|
|
|
Artifactview is designed to run behind a reverse proxy since it does not support HTTPS
|
|
by itself. If you are using a reverse proxy, you have to set the `REAL_IP_HEADER` option
|
|
to the client IP address header name provided by the proxy (usually `x-forwarded-for`.
|
|
Otherwise artifactview will assume it is being accessed by only 1 client (the proxy
|
|
itself) and the rate limiter would count all users as one.
|
|
|
|
### Docker Compose
|
|
|
|
Here is an example setup with docker-compose, using Traefik as a reverse proxy:
|
|
|
|
```yaml
|
|
services:
|
|
artifactview:
|
|
image: thetadev256/artifactview:latest
|
|
restart: unless-stopped
|
|
networks:
|
|
- proxy
|
|
environment:
|
|
ROOT_DOMAIN: av.thetadev.de
|
|
REAL_IP_HEADER: x-forwarded-for
|
|
GITHUB_TOKEN: github_pat_123456
|
|
REPO_WHITELIST: github.com;codeberg.org;code.thetadev.de
|
|
SITE_ALIASES: gh=>github.com;cb=>codeberg.org;th=>code.thetadev.de
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.docker.network=proxy"
|
|
- "traefik.http.routers.artifactview.entrypoints=websecure"
|
|
- "traefik.http.routers.artifactview.rule=HostRegexp(`^[a-z0-9-]*.?av.thetadev.de$`)"
|
|
|
|
networks:
|
|
proxy:
|
|
external: true
|
|
```
|
|
|
|
### Configuration
|
|
|
|
Artifactview is configured using environment variables.
|
|
|
|
| Variable | Default | Description |
|
|
| ------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `PORT` | 3000 | HTTP port |
|
|
| `CACHE_DIR` | /tmp/artifactview | Temporary directory where to store the artifacts |
|
|
| `ROOT_DOMAIN` | localhost:3000 | Public hostname+port number under which artifactview is accessible. If this is configured incorrectly, artifactview will show the error message "host does not end with configured ROOT_DOMAIN" |
|
|
| `RUST_LOG` | info | Logging level |
|
|
| `NO_HTTPS` | false | Set to True if the website is served without HTTPS (used if testing artifactview without an ) |
|
|
| `MAX_ARTIFACT_SIZE` | 100000000 (100 MB) | Maximum size of the artifact zip file to be downloaded |
|
|
| `MAX_FILE_SIZE` | 100000000 (100 MB) | Maximum contained file size to be served |
|
|
| `MAX_FILE_COUNT` | 10000 | Maximum amount of files within a zip file |
|
|
| `MAX_AGE_H` | 12 | Maximum age in hours after which cached artifacts are deleted |
|
|
| `ZIP_TIMEOUT_MS` | 1000 | Maximum time in milliseconds for reading the index of a zip file. If this takes too long, the zip file is most likely excessively large or malicious (zip bomb) |
|
|
| `GITHUB_TOKEN` | - | GitHub API token for downloading artifacts. Using a fine-grained token with public read permissions is recommended |
|
|
| `MEM_CACHE_SIZE` | 50 | Artifactview keeps artifact metadata as well as the zip file indexes in memory to improve performance. The amount of cached items is adjustable. |
|
|
| `REAL_IP_HEADER` | - | Get the client IP address from a HTTP request header<br />If Artifactview is exposed to the network directly, this option has to be unset. If you are using a reverse proxy the proxy needs to be configured to send the actual client IP as a request header.<br />For most proxies this header is `x-forwarded-for`. |
|
|
| `LIMIT_ARTIFACTS_PER_MIN` | 5 | Limit the amount of downloaded artifacts per IP address and minute |
|
|
| `REPO_BLACKLIST` | - | List of sites/users/repos that can NOT be accessed. The blacklist takes precedence over the whitelist (repos included in both lists cannot be accessed)<br />Example: `github.com/evil-corp/world-destruction;codeberg.org/blackhat;example.org` |
|
|
| `REPO_WHITELIST` | - | List of sites/users/repos that can ONLY be accessed. If the whitelist is empty, it will be ignored and any repository can be accessed. Uses the same syntax as `REPO_BLACKLIST`. |
|
|
| `SITE_ALIASES` | - | Aliases for sites to make URLs shorter<br />Example: `gh => github.com;cb => codeberg.org` |
|
|
| `SUGGESTED_SITES` | codeberg.org; github.com; gitea.com | List of suggested code forges (host only, without https://, separated by `;`). If repo_whitelist is empty, this value is used for the matched sites in the userscript. The first value is used in the placeholder URL on the home page. |
|
|
| `VIEWER_MAX_SIZE` | 500000 | Maximum file size to be displayed using the viewer |
|
|
|
|
## Technical details
|
|
|
|
### URL format
|
|
|
|
Artifactview uses URLs in the given format for accessing the individual artifacts:
|
|
`<HOST>--<USER>--<REPO>--<RUN>-<ARTIFACT>.hostname`
|
|
|
|
Example: `https://github-com--theta-dev--example-project--4-11.example.com`
|
|
|
|
The reason for using subdomains instead of URL paths is that many websites expect to be
|
|
served from a separate subdomain and access resources using absolute paths. Using URLs
|
|
like `example.com/github.com/theta-dev/example-project/4/11/path/to/file` would make the
|
|
application easier to host, but it would not be possible to simply preview a
|
|
React/Vue/Svelte web project.
|
|
|
|
Since domains only allow letters, numbers and dashes but repository names allow dots and
|
|
underscores, these escape sequences are used to access repositories with special
|
|
characters in their names.
|
|
|
|
- `-0` -> `.`
|
|
- `-1` -> `-`
|
|
- `-2` -> `_`
|
|
|
|
Another issue with using subdomains is that they are limited to a maximum of 63
|
|
characters. Most user and repository names are short enough for this not to become a
|
|
problem, but it could still happen that a CI run becomes inaccessible. Since the run ID
|
|
is incremented on each new CI run, it might even happen that Artifactview works fine at
|
|
the beginning of a project, but the subdomains exceed the length limit in the future.
|
|
|
|
That's why I added aliases for forge URLs. You can for example alias github.com as gh,
|
|
shaving 8 characters from the subdomain. This makes the subdomains short enogh that you
|
|
will be unlikely to hit the limit even with longer user/project names.
|
|
|
|
### Security considerations
|
|
|
|
It is recommended to use the whitelist feature to allow artifactview to access only
|
|
trusted servers, users and organizations.
|
|
|
|
Since many
|
|
[well-known URIs](https://www.iana.org/assignments/well-known-uris/well-known-uris.xhtml)
|
|
are used to configure security-relevant properties of a website or attest ownership of a
|
|
website (like `.well-known/acme-challenge` for issuing TLS certificates), Artifactview
|
|
will serve no files from the `.well-known` folder.
|
|
|
|
There is a configurable limit for both the maximum downloaded artifact size and the
|
|
maximum size of individual files to be served (100MB by default). Additionally there is
|
|
a configurable timeout for the zip file indexing operation. These measures should
|
|
protect the server againt denial-of-service attacks like overfilling the server drive or
|
|
uploading zip bombs.
|