{"id":15713541,"url":"https://github.com/watzon/paste69","last_synced_at":"2025-05-12T22:55:17.146Z","repository":{"id":198793418,"uuid":"701558932","full_name":"watzon/paste69","owner":"watzon","description":"Simple CURL-able pastebin","archived":true,"fork":false,"pushed_at":"2024-11-13T15:26:26.000Z","size":438,"stargazers_count":11,"open_issues_count":2,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-12T22:55:10.501Z","etag":null,"topics":["0x0","athena","athena-framework","crystal","crystal-lang","docker","pastebin","pastebin-api","pastebin-service"],"latest_commit_sha":null,"homepage":"https://0x45.st","language":"Crystal","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/watzon.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2023-10-06T23:06:46.000Z","updated_at":"2024-11-13T15:26:48.000Z","dependencies_parsed_at":"2023-10-15T03:49:04.794Z","dependency_job_id":"8ea2a6c5-da3e-47d6-a04c-a2c6dcfb0683","html_url":"https://github.com/watzon/paste69","commit_stats":null,"previous_names":["watzon/paste69"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fpaste69","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fpaste69/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fpaste69/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fpaste69/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/watzon","download_url":"https://codeload.github.com/watzon/paste69/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253837400,"owners_count":21971982,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["0x0","athena","athena-framework","crystal","crystal-lang","docker","pastebin","pastebin-api","pastebin-service"],"created_at":"2024-10-03T21:31:59.068Z","updated_at":"2025-05-12T22:55:17.096Z","avatar_url":"https://github.com/watzon.png","language":"Crystal","readme":"# Paste69\n\n\u003e [!WARNING]  \n\u003e Please see [0x45](https://github.com/watzon/0x45) for the successor to this project.\n\nThis project has undergone several changes, but here's where we are now:\nPaste69 is a clone of the popular pastebin service 0x45.st, but written in Crystal using [the Athena framework](https://athenaframework.org/) rather than in Python with Flask.\n\n## Differences from 0x0\n\nI have tried to keep feature parody with 0x0, but there are some small differences:\n\n- Multiple storage providers are supported (local and s3 for now)\n- The configuration format is slightly different, as are some config items\n\nSome features have also yet to be implemented. They will be coming in the near future. These features include:\n\n- NSFW detection\n- Virus scanning\n\n## Installation\n\nInstallation requires [Crystal](https://crystal-lang.org/) and Postgres. Other databases might be supported in the future.\n\nClone this repo:\n\n```bash\ngit clone https://github.com/watzon/paste69\n```\n\nInstall dependencies:\n\n```bash\nshards install\n```\n\nCopy and modify the config file:\n\n```bash\ncp config/config.example.yml config/config.yml\nvim config/config.yml\n```\n\nBuild the executables, migrate the database, and run the server:\n\n```bash\nshards build\n./bin/cli db:migrate # this assumes the dabase exists, if not run db:create first\n./bin/server\n```\n\n### Using Docker\n\nIf you want, you can build the Docker container yourself locally:\n\n```bash\ndocker build -v ./uploads:/app/uploads --tag paste69 ./docker\ndocker run -d -p 8080:8080 paste69\n```\n\nOr, you can use the hosted version available through ghcr:\n\n```bash\ndocker pull ghcr.io/watzon/paste69:main\ndocker run -d -p 8080:8080 ghcr.io/watzon/paste69:main\n```\n\nAll configuration items are available through environment variables, in addition to the config file. Configuration items and their environment variable names are listed below.\n\n## Configuration\n\nI've done my best to make Paste69 as zero configuration as possible. The default values listed in [src/services/config_manager.cr](src/services/config_manager.cr) should be sufficient for most deployments. However, should you wish to change any of the values you can do so through a config file, or using environment variables.\n\nValid config file locations are:\n\n- /etc/paste69/config.yml\n- ~/.paste69/config.yml\n- ~/.config/paste69/config.yml\n\nThe following table contains all available configuration options, their default values, and their environment variable counterparts:\n\n| Config Item                | Default Value             | Environment Variable       | Description                                         |\n|----------------------------|---------------------------|----------------------------|-----------------------------------------------------|\n| `host`                     | `\"0.0.0.0\"`               | `HOST`                     | Host to bind to                                     |\n| `port`                     | `8080`                    | `PORT`                     | Port to bind to                                     |\n| `site_url`                 | `\"0.0.0.0:8080\"`          | `SITE_URL`                 | Public URL of the site (used for generating links)  |\n| `database_url`             | `\"sqlite://./db/data.db\"` | `DATABASE_URL`             | URL of the database (Postgres and SQLite supported) |\n| `templates_dir`            | `\"src/templates\"`         | `TEMPLATES_DIR`            | Directory for template overrides (jinja2 format)    |\n| `max_content_length`       | `256 * 1024 * 1024`       | `MAX_CONTENT_LENGTH`       | Maximum size for incoming files                     |\n| `max_url_length`           | `4096`                    | `MAX_URL_LENGTH`           | Maximum size for shortened URLs                     |\n| `max_ext_length`           | `9`                       | `MAX_EXT_LENGTH`           | Maximum size for file extensions                    |\n| `storage.path`             | `\"./uploads\"`             | `STORAGE.PATH`             | Local storage path for files                        |\n| `storage.type`             | `\"local\"`                 | `STORAGE.TYPE`             | Type of storage to use (local or s3)                |\n| `storage.s3.region`        | `nil`                     | `STORAGE.S3.REGION`        | S3 region                                           |\n| `storage.s3.bucket`        | `nil`                     | `STORAGE.S3.BUCKET`        | S3 bucket                                           |\n| `storage.s3.access_key`    | `nil`                     | `STORAGE.S3.ACCESS_KEY`    | S3 access key                                       |\n| `storage.s3.secret_key`    | `nil`                     | `STORAGE.S3.SECRET_KEY`    | S3 secret key                                       |\n| `storage.secret_bytes`     | `16`                      | `STORAGE.SECRET_BYTES`     | Number of bytes to use for secrets                  |\n| `storage.ext_override`     | _too long_                | `STORAGE.EXT_OVERRIDE`     | File extension override map (mime =\u003e ext)           |\n| `storage.mime_blocklist`   | _too long_                | `STORAGE.MIME_BLOCKLIST`   | Array containing mime types to blocklist            |\n| `storage.upload_blocklist` | `nil`                     | `STORAGE.UPLOAD_BLOCKLIST` | Path to a file containing banned IP addresses       |\n| `nsfw.detect`              | `false`                   | `NSFW.DETECT`              | Enable NSFW detection (TODO)                        |\n| `nsfw.threshold`           | `0.608`                   | `NSFW.THRESHOLD`           | NSFW detection threshold                            |\n| `vscan.socket`             | `nil`                     | `VSCAN.SOCKET`             | ClamAV socket for virus scanning (TODO)             |\n| `vscan.quarantine_path`    | `\"./quarantine\"`          | `VSCAN.QUARANTINE_PATH`    | Path for quarantined files                          |\n| `vscan.interval`           | `604800`                  | `VSCAN.INTERVAL`           | How often to scan for viruses                       |\n| `vscan.ignore`             | _too long_                | `VSCAN.IGNORE`             | Mime types for which to ignore virus scanning       |\n| `url_alphabet`             | `\"01234567890abcdef...\"`  | `URL_ALPHABET`             | Alphabet string to use for shortened URL creation   |\n\n### Custom Templates\n\nPaste69 supports custom templates, which can be used to override the default templates. To do this, simply create a directory somewhere and copy the default templates from [src/templates](src/templates) into it. For example:\n\n```bash\nmkdir -p ~/.config/paste69/templates\ncp -r ./src/templates ~/.config/paste69/templates\n```\n\nand then update your config file (or set the TEMPLATES_DIR environment variable) to point to the new location.\n\n```diff\n*** ~/.config/paste69/config.yml 2024-01-01 12:00:00.000000000 -0500\n--- ~/.config/paste69/config.yml 2024-01-01 12:00:00.000000000 -0500\n@@ -1,1 +1,1 @@\n-templates_dir: \"src/templates\"\n+templates_dir: \"~/.config/paste69/templates\"\n```\n\nthis directory will be used __in stead of__ the default templates, and not in addition to, so be sure to copy all of the templates over.\n\n### IP Blocklisting\n\nIP blocklisting is supported. All uploads database entries _should_ contain an IP address, telling you where it was uploaded from. If you want to block a certain IP address (or even an entire subnet), you can create a file containing a list of IP addresses to block and upadate your config file with the path to the file. The file should contain a single IP address or subnet per line. For example:\n\n```text\n192.168.1.1\n172.16.17.32/24\n```\n\n## Development\n\nFeel free to make pull requests!\n\n## Contributing\n\n1. Fork it (\u003chttps://github.com/watzon/paste69/fork\u003e)\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Contributors\n\n- [Chris W](https://github.com/watzon) - creator and maintainer\n","funding_links":[],"categories":["\u003ca name=\"pastebin\"\u003e\u003c/a\u003ePastebin"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwatzon%2Fpaste69","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwatzon%2Fpaste69","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwatzon%2Fpaste69/lists"}