{"id":41834995,"url":"https://github.com/zipreport/zipreport-server","last_synced_at":"2026-01-25T09:03:42.313Z","repository":{"id":46105215,"uuid":"284938572","full_name":"zipreport/zipreport-server","owner":"zipreport","description":"PDF conversion daemon for ZipReport","archived":false,"fork":false,"pushed_at":"2026-01-24T06:26:51.000Z","size":161,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-24T16:45:41.582Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zipreport.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-08-04T09:44:09.000Z","updated_at":"2025-10-22T01:39:36.000Z","dependencies_parsed_at":"2024-06-21T01:06:26.791Z","dependency_job_id":"0fa8bd0a-fd43-4b0d-b3eb-cbe9a4754ab6","html_url":"https://github.com/zipreport/zipreport-server","commit_stats":{"total_commits":6,"total_committers":2,"mean_commits":3.0,"dds":"0.16666666666666663","last_synced_commit":"ae0b364f89b68aefa5f2dc74a3ff3e60da0d331e"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/zipreport/zipreport-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zipreport%2Fzipreport-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zipreport%2Fzipreport-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zipreport%2Fzipreport-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zipreport%2Fzipreport-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zipreport","download_url":"https://codeload.github.com/zipreport/zipreport-server/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zipreport%2Fzipreport-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28750653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T09:00:19.176Z","status":"ssl_error","status_checked_at":"2026-01-25T09:00:04.131Z","response_time":113,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-25T09:03:22.194Z","updated_at":"2026-01-25T09:03:42.306Z","avatar_url":"https://github.com/zipreport.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zipreport-server\n\n[![Go Version](https://img.shields.io/github/go-mod/go-version/zipreport/zipreport-server)](https://go.dev/)\n[![License](https://img.shields.io/github/license/zipreport/zipreport-server)](https://github.com/zipreport/zipreport-server/blob/development/LICENSE)\n[![CI](https://github.com/zipreport/zipreport-server/actions/workflows/ci.yml/badge.svg)](https://github.com/zipreport/zipreport-server/actions/workflows/ci.yml)\n[![Docker](https://github.com/zipreport/zipreport-server/actions/workflows/docker.yml/badge.svg)](https://github.com/zipreport/zipreport-server/actions/workflows/docker.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/zipreport/zipreport-server)](https://goreportcard.com/report/github.com/zipreport/zipreport-server)\n\nZipReport-server is the [zipreport](https://github.com/zipreport/zipreport) HTML to PDF conversion daemon, based on\n[rod](https://github.com/go-rod/rod) and Chromium, written in Go.\n\n**Note:** zipreport-server 2.xx only works with zipreport library version \u003e= 2.0.0 ,and it is **incompatible** with\nprevious\nversions.\n\n### Upgrading to version 2.3.0\n\nStarting with v2.3.0, zipreport-server uses an external configuration file and no longer bundles a self-signed certificate;\ninstead, mount a folder with a proper config.json (see [the sample configuration file](./config/config.sample.json)), and\noptionally modify and use [the sample script](./config/generate_certs.sh) to generate your own self-signed certificates;\nsee below for a docker-compose example, and check the [migration guide](./docs/migration-guide.md).\n\nAlso, please note that prometheus metrics are now exposed using a dedicated port, and metrics are disabled by default. Check\nthe [configuration file options](./docs/configuration.md) for available configuration parameters. \n\n### Security considerations\n\nzipreport-server relies on Chromium to render artifacts into PDF. As such, it allows unfettered execution of any\nexternal dependencies and scripts your template may use. This behavior may pose a security risk on certain\nenvironments.\nThe daemon also relies on the creation of ephemeral http servers on localhost as part of the rendering process.\n\n### How it works\n\nThe zipreport-server API receives a rendering request with an associated ZPT resource. For each rendering request,\nzipreport-server\nlaunches an internal http server to serve the ZPT content, and then instructs a Chromium instance to open the temporary\nurl and render to PDF.\n\nThe settling time for the internal HTML/JS rendering process can either be a default value in milisseconds (the default\nbehavior), or triggered by writing 'zpt-view-ready' to the JS console. By using the console approach, the PDF\ngeneration\nis triggered only after all dynamic canvas elements were generated.\n\n### Available endpoints\n\n#### [POST] /v2/render\n\n**Format:** multipart/form-data\n\n**Fields:**\n\n| Field             | Mandatory | Description                                                   |\n|-------------------|-----------|---------------------------------------------------------------|\n| report            | Yes       | Report file                                                   |\n| page_size         | Yes       | Page size (A5/A4/A3/Letter/Legal/Tabloid)                     |\n| margins           | Yes       | Margin type (none/minimal/standard)                           |\n| landscape         | No        | If true, print in landscape                                   |\n| script            | No        | Main html file (default report.html)                          |\n| settling_time     | No        | Settling time, in ms (default 200ms, see below)               |\n| timeout_job       | No        | Job timeout, in seconds (default 120s, see below)             | \n| timeout_js        | No        | JavaScript event timeout, in seconds (default 30s, see below) |\n| js_event          | No        | If true, wait for the javascript event (see below)            |\n| ignore_ssl_errors | No        | If true, ssl errors in referenced resources will be ignored   |\n\n**settling_time** (default: 200)\n\nValue in ms to wait after the DOM is ready to print the report. This setting is ignored if\njs_event is enabled.\n\n**timeout_job** (default 120)\n\nWaiting time, in seconds, to perform the conversion operation, including waiting times such as\nsettling_time.\n\n**timeout_js** (default 30)\n\nTime to wait, in seconds, for the javascript event to be triggered, before generating the\nreport anyway. Requires js_event to be true.\n\n**js_event**\n\nIf true, the system will wait upto timeout_js for a specific console message before\ngenerating the PDF. This allows for dynamic pages to signal when DOM manipulation is finished.\n\nTriggering example:\n\n```javascript\n\u003cscript\u003e\n    (function() {\n    // signal end of composition\n    console.log(\"zpt-view-ready\")\n})();\n\u003c/script\u003e\n```\n\n\n### Optional metrics endpoint (disabled by default)\n\n#### [GET] /metrics\n\nPrometheus metrics endpoint. Besides the default internal Go metrics, the following are provided:\n\n| metric                | type      | description                                                          |\n|-----------------------|-----------|----------------------------------------------------------------------|\n| total_requests        | counter   | Total conversion requests                                            |\n| total_request_success | counter   | Number of successful API calls                                       |\n| total_request_error   | counter   | Number of failed API calls                                           |\n| conversion_time       | histogram | Elapsed conversion time histogram, in seconds. The upper bound is 120 |\n| current_http_servers  | gauge     | Current internal HTTP server count                                   |\n| current_browsers      | gauge     | Current internal browser instance count                              |\n\n### Authentication\n\nzipreport-server performs header-based authentication using the token specified in your configuration file (`apiServer.options.authTokenSecret`). Clients must pass the authentication token in the `X-Auth-Key` header.\n\n**Environment Variable Override**\n\nThe API key can also be set via the `ZIPREPORT_API_KEY` environment variable, which takes precedence over the config file. This is useful for Docker deployments:\n\n```shell\ndocker run -p 6543:6543 -e ZIPREPORT_API_KEY=your-secret-key zipreport-server:2.3.1\n```\n\nExample:\n```bash\ncurl -X POST http://localhost:6543/v2/render \\\n  -H \"X-Auth-Key: your-secret-token\" \\\n  -F \"report=@report.zpt\" \\\n  -F \"page_size=A4\" \\\n  -F \"margins=standard\" \\\n  -F \"script=index.html\" \\\n  -o output.pdf\n```\n\nWithout authentication, requests will receive `401 Unauthorized`.\n\n### Running with Docker\n\nStarting with version 2.3.0, zipreport-server uses a configuration file. The Docker image includes a default configuration, so you can run with just the `ZIPREPORT_API_KEY` environment variable for basic usage. For advanced configuration, mount a custom config file to `/app/config/config.json`.\n\n**Multi-Platform Support**\n\nDocker images are built for both `linux/amd64` and `linux/arm64`. This enables running on:\n- Intel/AMD servers and desktops (amd64)\n- Apple Silicon Macs — M1/M2/M3/M4 (arm64)\n- ARM64 cloud instances — AWS Graviton, Ampere, etc.\n\nThe correct image is selected automatically by Docker based on the host architecture. Chromium is sourced from different locations depending on the platform:\n- **amd64**: Google's Chromium snapshots (same source as go-rod's default)\n- **arm64**: Playwright CDN (arm64 Chromium builds)\n\nBoth variants are functionally identical and store the browser in rod's expected cache location.\n\n**Quick Start**\n\n```shell\n# Build locally\ndocker build . --tag zipreport-server:2.3.1\n\n# Run with API key (uses default config, HTTP only, no TLS)\ndocker run -p 6543:6543 -e ZIPREPORT_API_KEY=your-secret-key zipreport-server:2.3.1\n```\n\n**Production Deployment with Custom Configuration**\n\nCreate a `config.json` file (see [config.sample.json](./config/config.sample.json) or [complete reference](./docs/configuration.md)):\n\n```json\n{\n  \"apiServer\": {\n    \"host\": \"\",\n    \"port\": 6543,\n    \"options\": {\n      \"authTokenSecret\": \"your-secure-random-token-here\",\n      \"defaultSecurityHeaders\": \"1\"\n    },\n    \"tlsEnable\": false\n  },\n  \"zipReport\": {\n    \"concurrency\": 8,\n    \"baseHttpPort\": 42000\n  },\n  \"log\": {\n    \"level\": \"info\"\n  }\n}\n```\n\nThen run with your configuration:\n\n```shell\n# Mount your configuration directory\ndocker run -p 6543:6543 \\\n  -v $(pwd)/config:/app/config \\\n  zipreport-server:2.3.1\n```\n\n**With TLS/HTTPS**\n\nGenerate certificates (or use your own):\n\n```shell\ncd config\n./generate_certs.sh\n```\n\nUpdate `config.json` to enable TLS:\n\n```json\n{\n  \"apiServer\": {\n    \"tlsEnable\": true,\n    \"tlsCert\": \"config/ssl/server.crt\",\n    \"tlsKey\": \"config/ssl/server.key\",\n    \"options\": {\n      \"authTokenSecret\": \"your-secure-random-token-here\"\n    }\n  }\n}\n```\n\nRun with TLS:\n\n```shell\ndocker run -p 6543:6543 \\\n  -v $(pwd)/config:/app/config \\\n  zipreport-server:2.3.1\n```\n\n**Using Prebuilt Image**\n\n```shell\n# Pull latest version\ndocker pull ghcr.io/zipreport/zipreport-server:latest\n\n# Or specific version\ndocker pull ghcr.io/zipreport/zipreport-server:2.3.1\n\n# Run with mounted configuration\ndocker run -p 6543:6543 \\\n  -v $(pwd)/config:/app/config \\\n  ghcr.io/zipreport/zipreport-server:2.3.1\n```\n\n**Docker Compose Example**\n\n```yaml\nversion: '3.8'\n\nservices:\n  zipreport:\n    image: ghcr.io/zipreport/zipreport-server:2.3.1\n    ports:\n      - \"6543:6543\"\n      - \"2220:2220\"  # Prometheus metrics (if enabled)\n    volumes:\n      - ./config:/app/config\n    restart: unless-stopped\n```\n\n**Configuration Options**\n\nSee [docs/configuration.md](./docs/configuration.md) for complete configuration reference with 70+ options including:\n- API server settings (host, port, timeouts, TLS)\n- Authentication configuration\n- Prometheus metrics endpoint\n- ZipReport rendering engine settings\n- Logging configuration with rotation\n\n**Migration from 2.2.x**\n\nIf upgrading from 2.2.x or earlier, see the [migration guide](./docs/migration-guide.md) for converting environment variables to the new configuration file format.\n\n### Build\n\n**Build Binaries**\n\n```shell\n# Build all binaries (zipreport-server and browser-update)\nmake build\n\n# Or just build\nmake\n```\n\nBinaries will be created in `./bin/`:\n- `bin/zipreport-server` - Main server binary\n- `bin/browser-update` - Browser download utility (fetches Chromium for the current platform)\n\n**Updating Chromium Versions**\n\nThe Chromium revision constants are defined in `pkg/browser/browser.go`:\n- `Revision` — Chromium snapshot revision for amd64 (must match rod's `RevisionDefault` so the launcher finds it in the cache)\n- `RevisionPlaywright` — Playwright CDN revision for arm64 Linux builds\n\nTo update the bundled Chromium version, change these constants and rebuild. The `browser-update` command will download the new version on next run.\n\n**Generate Self-Signed Certificates**\n\n```shell\n# Generate certificates in config/ssl/\ncd config\n./generate_certs.sh\n\n# Or using make (generates in cert/ directory)\nmake certificate\n```\n\n**Run Tests**\n\n```shell\n# Run all tests\nmake test\n\n# Run quick tests (skip long-running tests)\nmake test-short\n\n# Run with extended timeout\nmake test-integration\n```\n\n**Format Code**\n\n```shell\nmake fmt\n```\n\n**Run Server Locally**\n\n```shell\n# Make sure you have a configuration file\ncp config/config.sample.json config/config.json\n\n# Edit config.json with your settings\n\n# Run the server\n./bin/zipreport-server -c config/config.json\n\n# Or use default config location\n./bin/zipreport-server\n```\n\n## Sponsors\n\nThe [ZipReport Project](https://github.com/zipreport/) is sponsored exclusively by [BlackShield](https://blackshield.pt) \n\n\n## License \n\nMIT License - see LICENSE file for details\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzipreport%2Fzipreport-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzipreport%2Fzipreport-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzipreport%2Fzipreport-server/lists"}