{"id":24653998,"url":"https://github.com/afcms/luanti-skin-server","last_synced_at":"2025-10-07T14:30:20.539Z","repository":{"id":103042224,"uuid":"579942974","full_name":"AFCMS/luanti-skin-server","owner":"AFCMS","description":"⚠️ WIP Skin server for the Luanti engine","archived":false,"fork":false,"pushed_at":"2025-01-24T12:05:34.000Z","size":1389,"stargazers_count":8,"open_issues_count":43,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-24T12:24:56.953Z","etag":null,"topics":["golang","minetest","minetest-tool","react","server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AFCMS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-19T10:28:28.000Z","updated_at":"2025-01-24T12:05:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"38e6c3e1-59cb-4e7e-b1b4-f5ce4e7bf88c","html_url":"https://github.com/AFCMS/luanti-skin-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFCMS%2Fluanti-skin-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFCMS%2Fluanti-skin-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFCMS%2Fluanti-skin-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AFCMS%2Fluanti-skin-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AFCMS","download_url":"https://codeload.github.com/AFCMS/luanti-skin-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235633909,"owners_count":19021456,"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":["golang","minetest","minetest-tool","react","server"],"created_at":"2025-01-25T21:14:53.459Z","updated_at":"2025-10-07T14:30:20.533Z","avatar_url":"https://github.com/AFCMS.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Luanti Skin Server\n\n![GitHub Workflow Status](https://img.shields.io/github/checks-status/AFCMS/luanti-skin-server/master?style=flat-square)\n\n\u003e [!IMPORTANT]\n\u003e This server is still in development and is not ready for production use.\n\u003e Breaking changes may occur at any time.\n\nThis server is made for serving Luanti skins to Luanti servers. It is licensed under GPLv3.\n\n-   ✅ Easy to use and powerful **API**\n-   ✅ Skins compatible with both [**VoxeLibre**](https://content.luanti.org/packages/Wuzzy/mineclone2) and [**Minetest Game**](https://content.luanti.org/packages/Luanti/minetest_game)\n-   ✅ Fast and reliable, thanks to [**Docker**](https://www.docker.com), [**Golang**](https://go.dev), [**Fiber**](https://gofiber.io) and [**PostgreSQL**](https://www.postgresql.org)\n-   ✅ Optimised images using [**Oxipng**](https://github.com/shssoichiro/oxipng)\n\n## Design\n\nThe server is build with the [**Go**](https://go.dev) language on-top of the [**Fiber**](https://gofiber.io) framework.\n\nIt uses also the [**GORM**](https://gorm.io) library for interacting with the database.\n\nThe frontend is build with the [**React**](https://react.dev) library, the [**Vite**](https://vite.dev) framework\nand the following libraries:\n\n-   [**TailwindCSS**](https://tailwindcss.com) for styling\n-   [**HeadlessUI**](https://headlessui.com) for dialogs, combobox, etc\n-   [**Heroicons**](https://heroicons.com) for most icons\n-   [**React Router**](https://reactrouter.com)\n-   [**React Three Fiber**](https://github.com/pmndrs/react-three-fiber) for the 3D preview of skins\n\n## Running Server\n\n### Development\n\nWhile it's possible to develop the server without using Docker, it's much easier so only this method is documented.\n\n#### 1. Install Docker\n\nFollow the official guide for your OS.\n\n-   [Ubuntu](https://docs.docker.com/engine/install/ubuntu)\n-   [Debian](https://docs.docker.com/engine/install/debian)\n-   [Fedora](https://docs.docker.com/engine/install/fedora)\n-   [RHEL/CentOS](https://docs.docker.com/engine/install/centos)\n\n\u003e [!NOTE]\n\u003e The installation links are from Docker Engine, which works only under Linux.\n\u003e\n\u003e [Docker Desktop](https://www.docker.com/products/docker-desktop) can be used on Windows, MacOS and Linux.\n\u003e\n\u003e It runs a Linux VM in the background and isn't as performant as the native version, but it's easier to install and\n\u003e use.\n\n\u003e [!WARNING]\n\u003e You need a [BuildKit](https://docs.docker.com/build/buildkit) enabled version of Docker to build the image.\n\u003e\n\u003e In general both the image and the included Compose files use modern features of Docker and Docker Compose.\n\n#### 2. Install NodeJS\n\nInstall NodeJS v22 (`lts/jod`) following the [instructions](https://nodejs.org) for your system. I use [**nvm**](https://github.com/nvm-sh/nvm) under Linux.\n\nThen enable PNPM:\n\n```shell\ncorepack enable pnpm\n```\n\n#### 3. Download source code\n\n```shell\ngit clone https://github.com/AFCMS/luanti-skin-server \u0026\u0026 cd luanti-skin-server\n```\n\n#### 4. Configure server\n\n```shell\ncp exemple.env .env\n```\n\nEdit the `.env` file with the config you want.\n\nA typical development config would be:\n\n```ini\nMT_SKIN_SERVER_DATABASE_LOGGING=false\n\nMT_SKIN_SERVER_DB_HOST=db\nMT_SKIN_SERVER_DB_USER=user\nMT_SKIN_SERVER_DB_PASSWORD=azerty\nMT_SKIN_SERVER_DB_PORT=5432\nMT_SKIN_SERVER_DB_NAME=skin_server\n```\n\n#### 5. Run services\n\nRun backend:\n\n```shell\nCOMPOSE_BAKE=true docker compose -f compose.dev.yml up --build --watch\n```\n\nRun frontend:\n\n```shell\ncd frontend \u0026\u0026 pnpm install --include=dev \u0026\u0026 pnpm run dev\n```\n\nYou will now have access to the app (both frontend and API) at `http://127.0.0.1:8080`. Doing changes to the frontend\nfiles will trigger fast refresh without needing to restart the entire app.\n\n### Production\n\nThe supported method to run the server in production is using Docker Compose:\n\n```yaml\n---\nservices:\n    db:\n        image: \"postgres:17.4-alpine\"\n        restart: unless-stopped\n        environment:\n            - POSTGRES_USER=${MT_SKIN_SERVER_DB_USER}\n            - POSTGRES_PASSWORD=${MT_SKIN_SERVER_DB_PASSWORD}\n            - POSTGRES_DB=${MT_SKIN_SERVER_DB_NAME}\n            - DATABASE_HOST=${MT_SKIN_SERVER_DB_HOST}\n        expose:\n            - 5432\n        volumes:\n            - db:/var/lib/postgresql/data\n\n    server:\n        image: ghcr.io/afcms/luanti-skin-server:master\n        environment:\n            - MT_SKIN_SERVER_DB_USER=${MT_SKIN_SERVER_DB_USER}\n            - MT_SKIN_SERVER_DB_PASSWORD=${MT_SKIN_SERVER_DB_PASSWORD}\n            - MT_SKIN_SERVER_DB_NAME=${MT_SKIN_SERVER_DB_NAME}\n            - MT_SKIN_SERVER_DB_HOST=${MT_SKIN_SERVER_DB_HOST}\n            - MT_SKIN_SERVER_DB_PORT=${MT_SKIN_SERVER_DB_PORT}\n            - MT_SKIN_SERVER_DATABASE_LOGGING=${MT_SKIN_SERVER_DATABASE_LOGGING}\n            - MT_SKIN_SERVER_OAUTH_REDIRECT_HOST=${MT_SKIN_SERVER_OAUTH_REDIRECT_HOST}\n            - MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_ID=${MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_ID}\n            - MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_SECRET=${MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_SECRET}\n            - MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_ID=${MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_ID}\n            - MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_SECRET=${MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_SECRET}\n            - MT_SKIN_SERVER_FRONTEND_DEV_MODE=false\n            - MT_SKIN_SERVER_VERIFICATION_GOOGLE_SEARCH_CONSOLE=${MT_SKIN_SERVER_VERIFICATION_GOOGLE_SEARCH_CONSOLE}\n        ports:\n            - \"8080:8080\"\n        depends_on:\n            - db\n\nvolumes:\n    db:\n```\n\nIt uses the [production image](https://github.com/AFCMS/luanti-skin-server/pkgs/container/luanti-skin-server) built\nby the GitHub Actions workflow, which is based on `scratch` and supports `amd64` and `arm64` architectures.\n\n```shell\ndocker compose up\n```\n\nYou can verify that the image have been really built by the GitHub Actions workflow and find the build log using the GitHub CLI:\n\n```shell\ngh attestation verify oci://ghcr.io/afcms/luanti-skin-server:master --repo AFCMS/luanti-skin-server\n```\n\n\u003e [!NOTE]\n\u003e The server doesn't have TLS support, to keep it as minimal as possible. Fiber don't support HTTP/2 and HTTP/3 yet anyways.\n\u003e\n\u003e TLS should be handled by a reverse proxy like [Caddy](https://caddyserver.com) or [Traefik](https://traefik.io), which support HTTP/3 and allow easy use of Let's Encrypt, Cloudflare certificates, etc.\n\n#### Configuration\n\nFor production the server supports some more configuration variables.\n\n##### Google Search Console Verification\n\nThe server can use the HTML tag verification method for\nthe [Google Search Console](https://search.google.com/search-console) (URL prefix).\n\nYou can set the `MT_SKIN_SERVER_VERIFICATION_GOOGLE_SEARCH_CONSOLE` environment variable to Google's verification token.\n\nYou can also use the DNS record method if you want, please\ncheckout [Google's documentation](https://support.google.com/webmasters/answer/9008080) for more information.\n\n##### OAuth2\n\nThe server supports OAuth2 for authentication, you can set the following environment variables to enable it.\n\nIf one of the two variables (client id, client secret) for a provider are not set, OAuth2 will be disabled for that\nprovider.\n\n-   `MT_SKIN_SERVER_OAUTH_REDIRECT_HOST`: the host where the OAuth2 callback will be redirected to\n-   ContentDB:\n    -   `MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_ID`: the OAuth2 client ID for the ContentDB API\n    -   `MT_SKIN_SERVER_OAUTH_CONTENTDB_CLIENT_SECRET` the OAuth2 client secret for the ContentDB API\n    -   `MT_SKIN_SERVER_OAUTH_CONTENTDB_URL`: the URL of the ContentDB instance, default to `https://content.luanti.org`\n    -   [Create Application](https://content.luanti.org/user/apps/)\n-   GitHub:\n    -   `MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_ID`: the OAuth2 client ID for the GitHub API\n    -   `MT_SKIN_SERVER_OAUTH_GITHUB_CLIENT_SECRET` the OAuth2 client secret for the GitHub API\n    -   [Create Application](https://github.com/settings/applications/new)\n\n## Development Tools\n\nI recommand using either **VSCode** or **GoLand**.\n\nThere are multiple VSCode extensions marked as recommended for the workspace.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafcms%2Fluanti-skin-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fafcms%2Fluanti-skin-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fafcms%2Fluanti-skin-server/lists"}