{"id":50805545,"url":"https://github.com/firstof9/opensim-dotnet","last_synced_at":"2026-06-13T00:33:16.967Z","repository":{"id":360085202,"uuid":"1248623611","full_name":"firstof9/opensim-dotnet","owner":"firstof9","description":"A modern, containerized stack for running the OpenSim simulator and Robust grid services on .NET 8.0.","archived":false,"fork":false,"pushed_at":"2026-05-24T22:34:07.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T00:26:57.281Z","etag":null,"topics":["docker","docker-compose","dotnet","dotnet8","ghcr","github-actions","metaverse","opensim","opensimulator","robust","virtual-worlds"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","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/firstof9.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,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T22:05:40.000Z","updated_at":"2026-05-24T22:34:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/firstof9/opensim-dotnet","commit_stats":null,"previous_names":["firstof9/opensim-dotnet"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/firstof9/opensim-dotnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firstof9%2Fopensim-dotnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firstof9%2Fopensim-dotnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firstof9%2Fopensim-dotnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firstof9%2Fopensim-dotnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/firstof9","download_url":"https://codeload.github.com/firstof9/opensim-dotnet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/firstof9%2Fopensim-dotnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34268187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["docker","docker-compose","dotnet","dotnet8","ghcr","github-actions","metaverse","opensim","opensimulator","robust","virtual-worlds"],"created_at":"2026-06-13T00:33:14.140Z","updated_at":"2026-06-13T00:33:16.933Z","avatar_url":"https://github.com/firstof9.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# opensim-dotnet\n\n[![Build and Push Docker Image](https://github.com/firstof9/opensim-dotnet/actions/workflows/docker-build-push.yml/badge.svg)](https://github.com/firstof9/opensim-dotnet/actions/workflows/docker-build-push.yml)\n\nDocker container configurations for running [OpenSim](https://github.com/opensim/opensim) (Simulator and Robust grid services) on the modern **.NET 8.0 runtime**.\n\nImages are automatically built and published to the GitHub Container Registry (GHCR):\n- **Robust Grid Services**: `ghcr.io/firstof9/robust:latest`\n- **OpenSim Simulator**: `ghcr.io/firstof9/sim:latest`\n\n---\n\n## Directory Structure\n\n```text\nopensim-dotnet/\n├── .github/workflows/\n│   └── docker-build-push.yml  # GitHub Actions automated build/push pipeline\n├── robust/\n│   ├── Dockerfile             # Docker recipe for Robust Grid Services\n│   └── Robust.exe.config      # Default log4net config for Robust\n├── sims/\n│   ├── Dockerfile             # Docker recipe for the Simulator\n│   └── OpenSim.exe.config     # Default log4net config for OpenSim\n├── docker-compose.yml         # Docker Compose orchestration\n├── .gitignore\n├── LICENSE\n└── README.md\n```\n\n---\n\n## Getting Started: Host Setup\n\nBefore starting the containers, pre-create the host directories and configuration file placeholders. If you do not create them first, Docker Compose will create them automatically as directories owned by `root`, resulting in permission errors.\n\n### Standard Linux Setup\nRun the following commands in the root of your project directory:\n\n```bash\n# Create directories for configuration, persistent simulator data, and assets\nmkdir -p config persistence fsassets\n\n# Create empty configuration placeholders (which you will populate)\ntouch config/Robust.ini config/OpenSim.ini config/Regions.ini config/GridCommon.ini\n```\n\n### UGreen NAS (UGOS / UGOS Pro) Setup\nIf you are deploying on a UGreen NAS:\n1. **Directory Location:** The persistent directories should be created inside your shared `docker` folder, typically located at `/volume1/docker/` (e.g., `/volume1/docker/opensim-dotnet/`).\n2. **Setup via SSH:**\n   Connect to your NAS via SSH, navigate to your docker directory, and run the setup commands:\n   ```bash\n   cd /volume1/docker/\n   mkdir -p opensim-dotnet/config opensim-dotnet/persistence opensim-dotnet/fsassets\n   cd opensim-dotnet\n   touch config/Robust.ini config/OpenSim.ini config/Regions.ini config/GridCommon.ini\n   ```\n3. **Setup via File Manager:**\n   If you prefer using the File Manager GUI:\n   - Open **File Manager** and navigate to your `docker` shared folder.\n   - Create a folder named `opensim-dotnet`.\n   - Inside `opensim-dotnet`, create three folders: `config`, `persistence`, and `fsassets`.\n   - **Crucial:** You must create empty files named `Robust.ini`, `OpenSim.ini`, `Regions.ini`, and `GridCommon.ini` inside the `config` folder. Since the UGOS File Manager does not support direct file creation, create empty text files on your local computer with these exact names (ensuring there is no hidden `.txt` extension) and upload them to the `config/` directory. If you skip this, Docker will create them as directories during deployment, causing startup failures.\n\n---\n\n## Configuration \u0026 Volumes\n\nTailor the following mounted files and directories to your grid layout:\n\n### 1. Configuration Files (in `./config/`)\n- **`Robust.ini`**: Main configuration for Robust grid services.\n- **`OpenSim.ini`**: Main simulator configuration.\n- **`Regions.ini`**: Definitions of simulator regions.\n- **`GridCommon.ini`**: Shared configuration (database connection strings, service URLs) included by both OpenSim and Robust.\n\n### 2. Persistent Storage Directories\n- **`./fsassets/`**: Mapped directory where Robust stores binary asset data.\n- **`./persistence/`**: Mapped directory for simulator state and local databases (if using SQLite).\n- **`./imports/`** *(Optional)*: Commented out in `docker-compose.yml`; uncomment to import/export OAR/IAR files from/to the host.\n\n---\n\n## Orchestration (Docker Compose)\n\n### Standard Docker Compose\nSpin up both services with the provided `docker-compose.yml` file:\n\n```yaml\nservices:\n  robust:\n    image: ghcr.io/firstof9/robust:latest\n    container_name: robust-server\n    restart: unless-stopped\n    # Run as a non-root user (match your host user's UID and GID to avoid permission issues)\n    user: \"1000:1000\"\n    ports:\n      - \"8003:8003/tcp\"\n    environment:\n      - TZ=UTC # Replace with your local timezone, e.g., America/Phoenix\n      # DOTNET_GCConserveMemory specifies the Garbage Collector memory conservation level (1-9, where 9 is most aggressive).\n      - DOTNET_GCConserveMemory=4\n      # DOTNET_GCHighMemPercent specifies the GC memory limit high threshold percent in hexadecimal (0x4B = 75 in decimal).\n      - DOTNET_GCHighMemPercent=4B\n    volumes:\n      - ./config/Robust.ini:/home/opensim/opensim/bin/Robust.ini:ro\n      - ./config/GridCommon.ini:/home/opensim/opensim/bin/config-include/GridCommon.ini:ro\n      - ./fsassets:/home/opensim/opensim/bin/fsassets\n\n  sim:\n    image: ghcr.io/firstof9/sim:latest\n    container_name: sim-server\n    restart: unless-stopped\n    # Run as a non-root user (match your host user's UID and GID to avoid permission issues)\n    user: \"1000:1000\"\n    ports:\n      - \"9000:9000/tcp\"\n      - \"9000-9005:9000-9005/udp\"\n    environment:\n      - TZ=UTC # Replace with your local timezone, e.g., America/Phoenix\n      # DOTNET_GCConserveMemory specifies the Garbage Collector memory conservation level (1-9, where 9 is most aggressive).\n      - DOTNET_GCConserveMemory=4\n      # DOTNET_GCHighMemPercent specifies the GC memory limit high threshold percent in hexadecimal (0x4B = 75 in decimal).\n      - DOTNET_GCHighMemPercent=4B\n    volumes:\n      - ./config/Regions.ini:/home/opensim/opensim/bin/Regions/Regions.ini:ro\n      - ./config/OpenSim.ini:/home/opensim/opensim/bin/OpenSim.ini:ro\n      - ./config/GridCommon.ini:/home/opensim/opensim/bin/config-include/GridCommon.ini:ro\n      - ./persistence:/home/opensim/opensim/bin/persistence\n      # - ./imports:/home/opensim/opensim/bin/imports\n```\n\n### UGreen NAS Docker Compose\nFor deployments using the UGreen NAS Container Manager interface or SSH, relative volume paths (e.g., `./config/`) may not resolve correctly or can cause permission/startup errors. Use absolute paths pointing to your shared `docker` folder on the NAS (typically `/volume1/docker/opensim-dotnet/`).\n\nAdditionally, ensure the `user` GID/UID matches the NAS user who owns the folders (which you can check by running `id` via SSH).\n\nHere is the tailored `docker-compose.yml` for UGreen NAS:\n\n```yaml\nservices:\n  robust:\n    image: ghcr.io/firstof9/robust:latest\n    container_name: robust-server\n    restart: unless-stopped\n    # Run as your NAS user (replace with your UID:GID, e.g. 1000:1000 or 1001:1001)\n    user: \"1000:1000\"\n    ports:\n      - \"8003:8003/tcp\"\n    environment:\n      - TZ=UTC # Replace with your local timezone, e.g., America/Phoenix\n      # DOTNET_GCConserveMemory specifies the Garbage Collector memory conservation level (1-9, where 9 is most aggressive).\n      - DOTNET_GCConserveMemory=4\n      # DOTNET_GCHighMemPercent specifies the GC memory limit high threshold percent in hexadecimal (0x4B = 75 in decimal).\n      - DOTNET_GCHighMemPercent=4B\n    volumes:\n      - /volume1/docker/opensim-dotnet/config/Robust.ini:/home/opensim/opensim/bin/Robust.ini:ro\n      - /volume1/docker/opensim-dotnet/config/GridCommon.ini:/home/opensim/opensim/bin/config-include/GridCommon.ini:ro\n      - /volume1/docker/opensim-dotnet/fsassets:/home/opensim/opensim/bin/fsassets\n\n  sim:\n    image: ghcr.io/firstof9/sim:latest\n    container_name: sim-server\n    restart: unless-stopped\n    # Run as your NAS user (replace with your UID:GID, e.g. 1000:1000 or 1001:1001)\n    user: \"1000:1000\"\n    ports:\n      - \"9000:9000/tcp\"\n      - \"9000-9005:9000-9005/udp\"\n    environment:\n      - TZ=UTC # Replace with your local timezone, e.g., America/Phoenix\n      # DOTNET_GCConserveMemory specifies the Garbage Collector memory conservation level (1-9, where 9 is most aggressive).\n      - DOTNET_GCConserveMemory=4\n      # DOTNET_GCHighMemPercent specifies the GC memory limit high threshold percent in hexadecimal (0x4B = 75 in decimal).\n      - DOTNET_GCHighMemPercent=4B\n    volumes:\n      - /volume1/docker/opensim-dotnet/config/Regions.ini:/home/opensim/opensim/bin/Regions/Regions.ini:ro\n      - /volume1/docker/opensim-dotnet/config/OpenSim.ini:/home/opensim/opensim/bin/OpenSim.ini:ro\n      - /volume1/docker/opensim-dotnet/config/GridCommon.ini:/home/opensim/opensim/bin/config-include/GridCommon.ini:ro\n      - /volume1/docker/opensim-dotnet/persistence:/home/opensim/opensim/bin/persistence\n      # - /volume1/docker/opensim-dotnet/imports:/home/opensim/opensim/bin/imports\n```\n\nRun the stack in the background:\n```bash\ndocker compose up -d\n```\n\n### Environment Parameters (.NET Tuning)\nThe compose file includes .NET Garbage Collector settings configured to optimize resource utilization:\n- `DOTNET_GCConserveMemory=4`: Aggressively conserves memory usage (GC aggressiveness level 4).\n- `DOTNET_GCHighMemPercent=4B`: Restricts the GC high memory threshold to 75% (`4B` in hexadecimal) of host memory limits to prevent container OOM termination.\n- `TZ`: Defines the container timezone, aligning timestamps inside logs.\n\n---\n\n## Interactive Console Administration\n\nSince both services run in background detached mode, direct access to the command-line interfaces requires attaching to their interactive Docker TTYs.\n\n### Attaching to the Console\nTo attach to the simulator console or Robust grid services console:\n```bash\ndocker attach sim-server\n# OR\ndocker attach robust-server\n```\n\n### Safely Detaching\n\u003e [!WARNING]\n\u003e Do NOT use `Ctrl + C` to exit the attached console; doing so will send a kill signal and terminate the entire OpenSim/Robust server.\n\u003e\n\u003e To safely detach and leave the server running in the background, press:\n\u003e **`Ctrl + P`**, followed by **`Ctrl + Q`**.\n\n---\n\n## Advanced Configuration: Remote Console\n\nFor a more robust and secure administration method, you can set up OpenSim's built-in remote console (Telnet-based server) which allows you to log in without attaching to the container's standard input.\n\n1. In your `OpenSim.ini` (or `Robust.ini`), configure the `[Network]` section:\n   ```ini\n   [Network]\n     ConsoleUser = \"admin\"\n     ConsolePass = \"securepass123\"\n     ConsolePort = 9000\n   ```\n2. Set `Console = \"Connector\"` in the `[Startup]` section of the config.\n3. Access the console via any standard Telnet or SSH client pointing to the respective container port.\n\n---\n\n## Database Setup (SQLite vs. MariaDB/MySQL)\n\nBy default, standalone OpenSim instances utilize SQLite, storing database files inside the `./persistence/` directory.\n\n- **For production, multi-region, or grid deployments**, it is highly recommended to migrate/configure OpenSim and Robust to connect to an external **MariaDB/MySQL** database.\n- You can configure the database connection string in `GridCommon.ini` under the database settings:\n  ```ini\n  [DatabaseService]\n      StorageProvider = \"OpenSim.Data.MySQL.dll\"\n      ConnectionString = \"Data Source=db_host;Database=opensim;User ID=opensim;Password=secure_password;\"\n  ```\n- If desired, you can add a database service (such as `mariadb:10.11`) directly to your `docker-compose.yml` to keep the database container managed within the same stack.\n\n---\n\n## CI/CD Pipeline\n\nThe GitHub Actions workflow automatically:\n1. Rebuilds and pushes the images on every push to the `main` branch.\n2. Performs a daily cron build at **04:00 UTC** to pull the latest upstream OpenSim release from the repository releases redirect link, ensuring you are always up to date.\n\n---\n\n## License\n\nDistributed under the **MIT License**. See the `LICENSE` file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffirstof9%2Fopensim-dotnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffirstof9%2Fopensim-dotnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffirstof9%2Fopensim-dotnet/lists"}