A lightweight small-scale/private image hosting application. Mirror of https://code.itinerare.net/itinerare/Alcyone for accepting issues and pull requests!
  • PHP 72.7%
  • Blade 23.6%
  • SCSS 2.7%
  • JavaScript 0.8%
  • Dockerfile 0.2%
Find a file
2026-06-15 08:23:12 -04:00
.forgejo chore(deps): update mariadb:lts docker digest to b1c7bf8 2026-06-02 12:04:46 +00:00
app fix(users): filter data array in admin user update 2026-06-12 16:15:23 -04:00
bootstrap fix: re-add trust proxies env value 2026-01-14 11:32:57 -05:00
config feat: update to Laravel 12 (!546) 2026-01-06 20:46:40 +00:00
database refactor: rebuild on Laravel 11 application skeleton 2024-03-15 12:30:01 -04:00
docker fix(docker): add custom start script (!547) 2026-01-06 21:20:33 +00:00
public chore(deps): rebuild vite assets 2026-06-14 02:17:40 +00:00
resources feat: update to Laravel 12 (!546) 2026-01-06 20:46:40 +00:00
routes refactor: move scheduled commands to bootstrap/app 2025-12-22 18:43:06 -05:00
storage chore: fresh laravel installation 2023-10-06 14:39:17 -04:00
tests fix(tests): update PHPUnit, tests 2026-01-06 15:33:53 -05:00
.bladeformatterrc.json chore(deps-dev): set up JS deps, blade formatter 2023-10-06 14:51:49 -04:00
.bladeignore chore(deps-dev): set up JS deps, blade formatter 2023-10-06 14:51:49 -04:00
.dockerignore fix(docker): add custom start script (!547) 2026-01-06 21:20:33 +00:00
.editorconfig chore: fresh laravel installation 2023-10-06 14:39:17 -04:00
.env.example fix: re-add trust proxies env value 2026-01-14 11:32:57 -05:00
.gitattributes chore: fresh laravel installation 2023-10-06 14:39:17 -04:00
.gitignore chore: set up docker files 2025-12-22 18:43:06 -05:00
artisan refactor: rebuild on Laravel 11 application skeleton 2024-03-15 12:30:01 -04:00
CHANGELOG.md chore(release): v2.3.3 2026-06-15 08:23:12 -04:00
CODE_OF_CONDUCT.md docs: change CoC email 2023-11-03 16:04:24 -04:00
composer.json chore(release): v2.3.3 2026-06-15 08:23:12 -04:00
composer.lock chore(deps): update dependency guzzlehttp/guzzle to v7.11.1 2026-06-15 00:05:39 +00:00
Dockerfile chore(deps): update code.itinerare.net/internal/laravel-alpine:8.3 docker digest to 71c24ae 2026-06-14 20:04:57 +00:00
LICENSE docs: update readme, license year, example .env 2023-11-03 16:01:16 -04:00
package-lock.json chore(deps-dev): downgrade jquery 2026-06-12 16:23:57 -04:00
package.json chore(release): v2.3.3 2026-06-15 08:23:12 -04:00
phpunit.xml refactor: rebuild on Laravel 11 application skeleton 2024-03-15 12:30:01 -04:00
pint.json fix(tests): update PHPUnit, tests 2026-01-06 15:33:53 -05:00
README.md docs: update suggested docker compose in readme 2026-02-02 17:48:27 +00:00
renovate.json docs: add docker info to readme 2025-12-23 10:34:27 -05:00
vite.config.js refactor(deps): split up tinymce js 2025-09-18 09:44:49 -04:00

Alcyone

Alcyone is a lightweight small-scale/private image hosting application. It supports multiple users, with registration restricted via invitation code. Image uploads are private per user, with a content report flow if necessary, accessible without registration. Images are stored in webP for storage and performance savings, with the ability to generate and cache a png version for convenience.

Features

  • Support for multiple users, with permissions handled via a lightweight rank system (user/moderator/admin)
  • Users can upload (by default) images of up to 17MB, only visible personally on the site
    • Images are converted (if necessary) to webP for storage and performance savings
    • Images may be accessed via either a "web URL" (webP) or "share URL" (png); png images are cached for 24 hours and then removed to save on storage space
    • Users may delete their own images at will
  • A content report flow; content reports are created semi-anonymously (IP and optionally email address are recorded, the latter for notifications re report(s) only) and do not require registration
    • A report page accessible via key for access by the reporter
    • Reports are added to a queue accessible by moderators and admins, where they may be accepted (deleting the reported image), cancelled (preserving it), or the reporter banned (in the event of abuse of the report system)
    • Optional email notifications for the reporter on processing a report
  • Notifications (presently only used to notify an image's uploader that an image was removed as a result of a content report)
  • Light and dark themes (defaults to dark theme, adjustable in user settings for registered users)
  • 2FA for registered users
  • An invitation key system; invitation keys are necessary to register and may only be generated by site admin(s)
  • Minor rank editing (name and description), accessible only to admins
  • User index and editing, accessible only to admins
  • On-site editing for the terms of service and privacy policy pages
  • A lightweight admin/moderator panel
    • Moderators may access the index and reports queue
    • Admins have access to all functions
  • Backup handling including optional Dropbox support

Setup

From Source

Obtain a copy of the code

$ git clone https://code.itinerare.net/itinerare/alcyone.git

Configure .env in the directory

$ cp .env.example .env
  • See here for a list of PHP-supported time zones.
  • You will need to provide email information; in a pinch services that allow sending email via SMTP will do.

Setting up

Install packages with composer:

$ composer install

Generate app key, create the database, and run migrations:

$ php artisan key:generate
$ php artisan migrate

Perform general site setup:

$ php artisan setup-alcyone

Ensure that the scheduler is added to cron, like so:

* * * * * cd ~/site-name.com/www && php artisan schedule:run >> /dev/null 2>&1

Via Docker Compose

An example docker-compose file is as follows:

services:
    # Runs the web application
    app:
        image: code.itinerare.net/itinerare/alcyone:latest
        restart: always
        ports:
            - '127.0.0.1:8080:80'
        env_file:
            - .env
        environment:
            - CONTAINER_ROLE=app
            - PHP.post_max_size=17M
            - PHP.upload_max_filesize=17M
        healthcheck:
            test: ["CMD-SHELL", "curl -so /dev/null http://localhost/ || exit 1"]
            interval: 30s
            timeout: 10s
            retries: 3
            start_period: 5s
        volumes:
            - ./data/images:/var/www/public/images/

    # Runs scheduled commands
    scheduler:
        image: code.itinerare.net/itinerare/alcyone:latest
        restart: always
        depends_on:
            - app
        env_file:
            - .env
        environment:
            - CONTAINER_ROLE=scheduler
        healthcheck:
            test: ["CMD", "php", "/var/www/artisan", "health:check", "--component=database"]
            interval: 30s
            timeout: 10s
            retries: 3
            start_period: 40s
        volumes:
            - ./data/images:/var/www/public/images/

For more configuration options, see the base image's readme.

You will need to set up the .env file manually before starting Alcyone. Copy the example .env alongside docker-compose.yml; to generate a key, docker run --rm code.itinerare.net/itinerare/alcyone:latest php artisan key:generate --show can be used and its final output (base64:etcetc...) copied into the .env file (as APP_KEY).

After running docker compose up -d, run docker exec -i alcyone-app-1 php artisan setup-alcyone (replacing alcyone-app-1 with the relevant container name if it is different) to perform initial set-up.

While the application container can theoretically be exposed directly, it's recommended to run it behind nginx or similar with SSL certificates. If doing so, uncomment and switch ALCYONE_TRUST_PROXIES in the .env file to true.

An example nginx config is as follows:

server {
    server_name site.com www.site.com;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://127.0.0.1:8080;
        break;
    }
}

Contact

If you have any questions, please contact me via email at [email protected].