Compare commits

...

345 Commits

Author SHA1 Message Date
7e59315e3d feat: Add rootless Docker support
Implements #547 - Add support for rootless Docker images to avoid permission issues.

Key changes:
- Add Dockerfile.rootless that runs as UID 1000 by default
- Create simplified entrypoint script without chown operations
- Add build-rootless.py to build rootless variants with -rootless suffix
- Document rootless usage in README-ROOTLESS.md
- Update main README with rootless section

The rootless images eliminate common permission problems by:
- Running as non-root from the start (USER 1000:1000)
- Avoiding recursive chown operations that can cause race conditions
- Using open permissions (777) on directories during build
- Not supporting PUID/PGID environment variables

This provides a cleaner solution for rootless Docker users and those
experiencing permission issues with volumes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-03 20:07:42 +09:00
9464758a7b Updated mods updater script to correctly process mod dependencies (#557)
Co-authored-by: Victor <victor@blockbank.ai>
2025-07-03 19:48:23 +09:00
50f04fb096 Fix README tag pollution from update script (#573)
* fix: Improve README tag generation to reduce clutter

- Modified update.sh to only show the latest and stable versions
- Removed duplicate major.minor version tags
- Changed from listing all versions to showing only the most relevant tags
- Fixed jq query to properly detect stable version using index() instead of contains()

This significantly reduces README pollution by showing only:
- The latest experimental version with its tags
- The current stable version with its tags
- One entry per major.minor version for older releases (removed from this commit)

Before: 60+ lines of tags with many duplicates
After: 2 lines showing only latest and stable versions

* fix: Address shellcheck warnings about subshell variable modifications

- Changed from pipeline to process substitution to avoid SC2030/SC2031 warnings
- Variables modified in the while loop are now properly preserved
- This ensures readme_tags modifications are not lost in subshells
2025-07-03 19:45:29 +09:00
15d31c9a2e docs: Add documentation for PRESET environment variable (#572)
- Add PRESET to the environment variables table
- Include detailed explanation of available preset values
- Add example showing how to use PRESET when generating a new map
- Document that PRESET is optional and only used with GENERATE_NEW_SAVE=true

Fixes #571

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-03 19:32:40 +09:00
8784845385 Add CLAUDE.md with project guidance for Claude Code
- Project overview and architecture description
- Common development commands for building and testing
- Environment variables and configuration details
- Version management and automated update process
- Volume structure and data organization

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-03 19:22:52 +09:00
9f6c781331 Auto Update Factorio to stable version: 2.0.55 experimental version: 2.0.58 2025-06-23 15:28:19 +00:00
8a718705b7 Auto Update Factorio to stable version: 2.0.55 experimental version: 2.0.57 2025-06-19 17:23:31 +00:00
60277e89f1 Update README_zh_CN.md (#569) 2025-06-18 18:26:44 +09:00
4562f675ea Auto Update Factorio to stable version: 2.0.55 experimental version: 2.0.55 2025-06-05 10:28:37 +00:00
22d02c42fa Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.55 2025-06-02 18:35:06 +00:00
6b3dd77a54 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.54 2025-05-30 16:31:26 +00:00
6d3be9aef1 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.52 2025-05-30 13:34:06 +00:00
bf97066b9c Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.53 2025-05-30 11:19:55 +00:00
c0c235a28d Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.52 2025-05-23 11:20:05 +00:00
d5db1b1281 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.51 2025-05-19 12:53:01 +00:00
0c0349b5d6 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.50 2025-05-16 11:20:16 +00:00
0c1b2f4164 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.49 2025-05-12 17:21:44 +00:00
b36cd87194 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.48 2025-05-12 11:20:54 +00:00
e82cead5f4 Auto Update Factorio to stable version: 2.0.47 experimental version: 2.0.47 2025-05-05 15:26:04 +00:00
d9ff25fa10 Auto Update Factorio to stable version: 2.0.43 experimental version: 2.0.47 2025-04-29 19:19:23 +00:00
b7fdff9b94 Auto Update Factorio to stable version: 2.0.43 experimental version: 2.0.46 2025-04-29 10:27:22 +00:00
04f20de96c Auto Update Factorio to stable version: 2.0.43 experimental version: 2.0.45 2025-04-14 17:21:17 +00:00
fcd2c2e40e Auto Update Factorio to stable version: 2.0.43 experimental version: 2.0.44 2025-04-07 17:20:58 +00:00
f02c02f38e Bump peter-evans/dockerhub-description from 4.0.1 to 4.0.2 (#567)
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-version: 4.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 11:29:11 +09:00
b4be6993c6 Bump peter-evans/dockerhub-description from 4.0.0 to 4.0.1 (#566)
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 10:47:21 +09:00
a2c11ade50 Auto Update Factorio to stable version: 2.0.43 experimental version: 2.0.43 2025-03-31 13:32:20 +00:00
b334d27cf0 Fix watchtower also updating other containers (#565) 2025-03-31 10:37:23 +09:00
ede09dc402 Auto Update Factorio to stable version: 2.0.42 experimental version: 2.0.43 2025-03-26 14:23:35 +00:00
0929686ad3 Auto Update Factorio to stable version: 2.0.42 experimental version: 2.0.42 2025-03-21 18:31:36 +00:00
317d3731e8 Auto Update Factorio to stable version: 2.0.41 experimental version: 2.0.42 2025-03-19 20:25:30 +00:00
080a70f6be Auto Update Factorio to stable version: 2.0.41 experimental version: 2.0.41 2025-03-14 12:44:07 +00:00
83bffe4b13 Auto Update Factorio to stable version: 2.0.39 experimental version: 2.0.41 2025-03-12 21:21:19 +00:00
14df05cd6d Auto Update Factorio to stable version: 2.0.39 experimental version: 2.0.40 2025-03-12 11:18:51 +00:00
c0e1bae277 Auto Update Factorio to stable version: 2.0.39 experimental version: 2.0.39 2025-03-11 10:25:24 +00:00
370059f2f6 Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.39 2025-03-05 18:32:32 +00:00
7e8c89c02a Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.38 2025-03-04 12:45:59 +00:00
1e52dc48c9 Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.37 2025-02-26 19:17:45 +00:00
14aa945717 Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.36 2025-02-26 15:25:49 +00:00
57bbf46196 Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.35 2025-02-20 12:44:29 +00:00
090e771c0c Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.34 2025-02-06 19:17:57 +00:00
9e89a7930e Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.33 2025-01-28 13:25:05 +00:00
20e6176a85 Auto Update Factorio to stable version: 2.0.32 experimental version: 2.0.32 2025-01-23 14:20:03 +00:00
e5e1993c97 Auto Update Factorio to stable version: 2.0.30 experimental version: 2.0.32 2025-01-21 14:20:23 +00:00
6e0ea49985 Auto Update Factorio to stable version: 2.0.28 experimental version: 2.0.32 2025-01-20 15:22:49 +00:00
f757e538b7 Auto Update Factorio to stable version: 2.0.28 experimental version: 2.0.31 2025-01-16 15:22:26 +00:00
a94f8a0d4e Auto Update Factorio to stable version: 2.0.28 experimental version: 2.0.30 2025-01-10 12:43:54 +00:00
2b76185f94 Auto Update Factorio to stable version: 2.0.28 experimental version: 2.0.29 2025-01-06 11:18:02 +00:00
3c45811e15 Auto Update Factorio to stable version: 2.0.28 experimental version: 2.0.28 2024-12-21 11:15:51 +00:00
8990021fa1 Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.28 2024-12-20 14:19:30 +00:00
50e5c868e5 Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.27 2024-12-18 17:20:05 +00:00
89aebaba4b Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.26 2024-12-16 18:32:47 +00:00
d19c97c075 Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.25 2024-12-12 18:33:00 +00:00
19e5dc7532 Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.24 2024-12-05 15:25:48 +00:00
6a3b160d76 Auto Update Factorio to stable version: 2.0.23 experimental version: 2.0.23 2024-12-02 09:26:26 +00:00
a3d5456e58 Auto Update Factorio to stable version: 2.0.21 experimental version: 2.0.23 2024-11-28 16:28:35 +00:00
8d5096e28b Auto Update Factorio to stable version: 2.0.21 experimental version: 2.0.22 2024-11-26 17:20:59 +00:00
a1135b6a55 Auto Update Factorio to stable version: 2.0.21 experimental version: 2.0.21 2024-11-25 08:30:43 +00:00
192f686b6b Auto Update Factorio to stable version: 2.0.20 experimental version: 2.0.21 2024-11-21 18:31:18 +00:00
66ce43c0ca Auto Update Factorio to stable version: 2.0.20 experimental version: 2.0.20 2024-11-19 14:22:24 +00:00
ebadd1d8b8 Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.20 2024-11-18 16:20:02 +00:00
c9989d3a07 Added hint about how stable and experimental tags works since 2.0
Fixes #526
2024-11-17 01:59:40 +01:00
2dfaac7ec4 Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.19 2024-11-15 18:30:41 +00:00
c2d7c5696e Add rcon client (#550)
* Add rcon client to container

* Explain rcon command

* Remove test container name

* Apply suggestions

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>

* Add example docker-compose file

* Clarify return code

* Switch to pre-update

* Update docker-compose.yml

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>

* Allow build support for build (/* is only possible in buildx)

* Added version information in README.md

---------

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>
2024-11-14 19:41:25 +01:00
f14bedbc63 Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.18 2024-11-14 18:35:40 +00:00
d91c45fa62 Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.17 2024-11-12 18:29:03 +00:00
2092e86aec Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.16 2024-11-08 15:22:53 +00:00
ecb89b0c11 Auto Update Factorio to stable version: 2.0.15 experimental version: 2.0.15 2024-11-08 08:27:04 +00:00
42a08a95d4 Added extra_host example for NAS (#542)
* Added extra_host example for NAS

Took 11 minutes

* 🎨

Took 3 minutes
2024-11-08 00:13:38 +01:00
61d52eaa7c Auto Update Factorio to stable version: 2.0.14 experimental version: 2.0.15 2024-11-05 17:19:51 +00:00
6916fcb150 Auto Update Factorio to stable version: 2.0.14 experimental version: 2.0.14 2024-11-03 12:36:15 +00:00
8c9dfd004e Use stable_online_version instead of stableOnlineVersionShort
This hopefully causes the stable tag to not be removed anymore for an unknown reason.
2024-11-01 17:50:52 +01:00
867635db16 Auto Update Factorio to stable version: 2.0.13 experimental version: 2.0.14 2024-11-01 15:23:21 +00:00
b7413607c4 Auto Update Factorio to stable version: 2.0.13 experimental version: 2.0.14 2024-11-01 14:20:23 +00:00
5d6f70b285 Auto Update Factorio to stable version: 2.0.13 experimental version: 2.0.13 2024-10-31 15:23:56 +00:00
a24e42b281 Auto Update Factorio to stable version: 2.0.13 experimental version: 2.0.13 2024-10-31 14:20:50 +00:00
d1142e3408 Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.13 2024-10-31 13:28:03 +00:00
4eb53b6e48 Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.12 2024-10-31 12:43:16 +00:00
f986f1c870 Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.13 2024-10-30 20:23:47 +00:00
bc760a9599 Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.13 2024-10-30 19:18:52 +00:00
d153e30f1c Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.12 2024-10-29 13:29:24 +00:00
cc5061d339 Auto Update Factorio to stable version: 2.0.12 experimental version: 2.0.12 2024-10-29 12:44:42 +00:00
14ae422463 Auto Update Factorio to stable version: 2.0.11 experimental version: 2.0.12 2024-10-28 18:30:19 +00:00
88ca95a1ae Auto Update Factorio to stable version: 2.0.11 experimental version: 2.0.12 2024-10-28 17:20:48 +00:00
64980b9db3 using absolute path over relative path for subscripts (#538) 2024-10-27 19:49:15 +01:00
85f8011105 Update README_zh_CN.md (#535)
fix spelling typo
2024-10-26 16:33:42 +02:00
cc8d89df84 Auto Update Factorio to stable version: 2.0.11 experimental version: 2.0.11 2024-10-26 09:20:52 +00:00
956ade4f0b Auto Update Factorio to stable version: 2.0.11 experimental version: 2.0.11 2024-10-26 08:25:28 +00:00
049d34ea9a Auto Update Factorio to stable version: 2.0.10 experimental version: 2.0.11 2024-10-25 16:27:26 +00:00
d01580b5a5 Auto Update Factorio to stable version: 2.0.10 experimental version: 2.0.11 2024-10-25 15:22:54 +00:00
25a283ad79 Readded REPO_TOKEN in checkout, because workflows are not triggered.
related #526
2024-10-24 16:17:01 +02:00
b172b16ff4 Auto Update Factorio to stable version: 2.0.10 experimental version: 2.0.10 2024-10-24 14:01:05 +00:00
eb150cff0d Auto Update Factorio to stable version: 2.0.10 experimental version: 2.0.10 2024-10-24 13:59:37 +00:00
b20d93e229 Change DLC_SPACE_AGE to enable specific Space Age mods (#530)
* Change variable DLC_SPACE_AGE to allow listing specific Space Age mods to enable

* Adjust DLC_SPACE_AGE note

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>

---------

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>
2024-10-23 23:54:02 +02:00
9562212254 Filter for path and remove tags
related #526
2024-10-23 23:53:11 +02:00
6060c7b722 Auto Update Factorio to stable version: 2.0.9 experimental version: 2.0.10 2024-10-23 21:20:20 +00:00
06baf6a186 Auto Update Factorio to stable version: 2.0.9 experimental version: 2.0.10 2024-10-23 20:24:52 +00:00
6eb0cd96d8 MODS is available since 2.0.8
Took 11 minutes
2024-10-23 17:24:05 +02:00
bbbfef343c Auto Update Factorio to stable version: 2.0.9 experimental version: 2.0.9 2024-10-23 11:18:00 +00:00
44a58b056c Auto Update Factorio to stable version: 2.0.9 experimental version: 2.0.9 2024-10-23 10:23:09 +00:00
e37bcf1ed0 Create base mod-list.json if it does not exist (#523) 2024-10-22 23:54:00 +02:00
3defd74c46 Merge branch 'hjhixon-patch-1' 2024-10-22 23:41:12 +02:00
dde2761a8c fix entrypoint logic for checking if root 2024-10-22 23:40:47 +02:00
0ec91c3391 Add documentation for env variable MODS and make it actually change the mod directory (#520) 2024-10-22 23:22:20 +02:00
f9040c7450 Added missing environment variable
Took 20 minutes
2024-10-22 21:23:58 +02:00
c9957b7d76 Auto Update Factorio to stable version: 2.0.8 experimental version: 2.0.9 2024-10-22 19:19:24 +00:00
89ae20012e Added DLC_SPACE_AGE environment variable (#519)
* Added DLC_SPACE_AGE environment variable to enable or disable dlc related mods

Took 53 minutes

* 🎨

Took 2 minutes
2024-10-22 20:40:34 +02:00
d137f32c2f Auto Update Factorio to stable version: 2.0.8 experimental version: 2.0.9 2024-10-22 18:29:48 +00:00
4f3c5f2e93 Do not run the build in pull requests
Took 6 minutes
2024-10-22 19:33:29 +02:00
f7e9dea263 Improve logging in updating mods (#518)
Took 55 minutes
2024-10-22 19:28:25 +02:00
748dec4ad5 Fixed tag match in update (#515)
Took 38 minutes
2024-10-22 07:40:13 +02:00
3ce89a714b Auto Update Factorio to stable version: 2.0.8 experimental version: 2.0.8 2024-10-22 05:21:25 +00:00
a8ecb01f4c Bump peter-evans/dockerhub-description from 2.4.1 to 4.0.0 (#512)
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 2.4.1 to 4.0.0.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v2.4.1...v4.0.0)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 06:48:30 +02:00
6692bb514d Bump actions/checkout from 2 to 4 (#513)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 06:48:03 +02:00
2d805feb4f Cleanup github workflows
Took 9 minutes
2024-10-22 06:46:18 +02:00
bc2dc44cad Removed old 2.0.7 release
Related #511
2024-10-22 06:35:03 +02:00
04085ef23d Auto Update Factorio to stable version: 2.0.8 experimental version: 2.0.8 2024-10-21 21:20:17 +00:00
fbb787e535 Auto Update Factorio to stable version: 2.0.7 experimental version: 2.0.8 2024-10-21 18:30:01 +00:00
2ba59b4f95 build: build in reverse order of versions (#506)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-10-21 16:00:49 +02:00
c269289a96 Improve image stages (#509)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-10-21 15:59:34 +02:00
ee0388e163 Auto Update Factorio to stable version: 2.0.7 experimental version: 2.0.7 2024-10-21 12:52:02 +00:00
a1cb15b709 Updated update.sh and clear data from broken github action! (#505)
* Update update.sh to fix SHA256 grabbing

* Update buildinfo.json reverted data so build.sh can run

* Update docker-compose.yml  reverted data so build.sh can run
2024-10-21 14:51:42 +02:00
890489fb15 Auto Update Factorio to stable version: 2.0.7 experimental version: 2.0.7 2024-10-21 11:14:31 +00:00
c756ffe827 Auto Update Factorio to stable version: 1.1.110 experimental version: 1.1.110 2024-08-27 19:15:55 +00:00
4474b52473 Auto Update Factorio to stable version: 1.1.110 experimental version: 1.1.110 2024-08-27 18:27:09 +00:00
84a808102f Auto Update Factorio to stable version: 1.1.109 experimental version: 1.1.110 2024-08-16 17:17:42 +00:00
016c5cf3b5 Auto Update Factorio to stable version: 1.1.109 experimental version: 1.1.109 2024-07-02 14:17:09 +00:00
159b14bd8e Auto Update Factorio to stable version: 1.1.109 experimental version: 1.1.109 2024-07-02 13:21:23 +00:00
c1b0f6ca83 Add versioned "stable" tag. i.e. "stable-<major>.<minor>.<patch>" (#490) 2024-06-12 20:12:58 +09:00
965fef7ac2 Removed versions 2024-06-12 20:12:27 +09:00
88fed07073 container label for factorio version (#493) 2024-06-12 19:48:50 +09:00
4ab4c889f4 Add support for --preset options provided by vanilla and popular mods (#482)
* Add support for --preset options provided by vanilla and popular mods

* Add support for --preset in scenario.sh

* Replace SU_EXEC with EXEC
2024-06-12 19:47:42 +09:00
bc28f4a917 Added missing envsubst command
Fixes #489
2024-06-12 19:46:53 +09:00
d792589c56 Auto Update Factorio to stable version: 1.1.107 experimental version: 1.1.109 2024-06-07 14:18:34 +00:00
486c0f1d0a Auto Update Factorio to stable version: 1.1.107 experimental version: 1.1.108 2024-05-31 10:19:43 +00:00
80d8761520 Auto Update Factorio to stable version: 1.1.107 experimental version: 1.1.107 2024-04-18 15:18:17 +00:00
f4e0e640c5 Auto Update Factorio to stable version: 1.1.107 experimental version: 1.1.107 2024-04-18 14:16:47 +00:00
51b601b8b6 Auto Update Factorio to stable version: 1.1.104 experimental version: 1.1.107 2024-04-11 16:20:33 +00:00
1d88d18b38 Auto Update Factorio to stable version: 1.1.104 experimental version: 1.1.106 2024-03-26 12:32:10 +00:00
7d085d7fe5 Auto Update Factorio to stable version: 1.1.104 experimental version: 1.1.105 2024-03-20 15:18:36 +00:00
630c5a1864 Install procps for ps command used in kubernetes probes (#487)
Co-authored-by: Florian Kinder <florian.kinder@enthus.de>
2024-03-09 16:05:48 +09:00
98d3e475d3 add support for ARM (#485)
* build and run on arm64

* multiarch docker build

* add ARM64 warning to README.md
2024-03-03 12:09:41 +09:00
bd76f1c541 Swap to Debian slim baseimage (#469)
* Swap to Debian slim baseimage

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>

* Only install necessary packages

---------

Co-authored-by: Doridian <git@doridian.net>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
2024-03-03 11:57:47 +09:00
afde97243d Auto Update Factorio to stable version: 1.1.104 experimental version: 1.1.104 2024-02-14 13:18:06 +00:00
81b476ac97 Auto Update Factorio to stable version: 1.1.104 experimental version: 1.1.104 2024-02-14 12:31:41 +00:00
30e56a197c Auto Update Factorio to stable version: 1.1.101 experimental version: 1.1.104 2024-01-30 14:15:37 +00:00
effd07f84c Auto Update Factorio to stable version: 1.1.101 experimental version: 1.1.103 2024-01-19 16:23:28 +00:00
23d40f36de Auto Update Factorio to stable version: 1.1.101 experimental version: 1.1.102 2024-01-18 13:21:53 +00:00
250a90de53 Auto Update Factorio to stable version: 1.1.101 experimental version: 1.1.101 2024-01-10 13:21:19 +00:00
89f601e5ce Auto Update Factorio to stable version: 1.1.101 experimental version: 1.1.101 2024-01-10 12:34:39 +00:00
73fe111bea Auto Update Factorio to stable version: 1.1.100 experimental version: 1.1.101 2023-12-26 12:32:06 +00:00
18b455ba43 Auto Update Factorio to stable version: 1.1.100 experimental version: 1.1.100 2023-12-11 22:17:25 +00:00
1c5e98f289 Auto Update Factorio to stable version: 1.1.100 experimental version: 1.1.100 2023-12-11 21:15:24 +00:00
0a3d923c5b Remove updater badge 2023-12-10 22:21:03 +01:00
19f52a6ce0 Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.100 2023-12-04 10:20:44 +00:00
f6461d99be Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.99 2023-11-28 10:19:49 +00:00
f5a9224756 Updated checksum based on https://www.factorio.com/download/sha256sums/
Issue reported in https://forums.factorio.com/viewtopic.php?f=3&p=597231#p597231
2023-11-23 14:06:42 +01:00
79eebfb0f9 Removed older versions 2023-11-23 14:02:19 +01:00
b75bce7f91 Update buildinfo.json for new build in 1.1.98 (#480)
resolves https://github.com/factoriotools/factorio-docker/issues/479
2023-11-23 13:56:39 +01:00
ef449c4763 Update buildinfo.json
Sorry for the mixup. Reverting this change by editing it again, not by rolling back the code. You can remove my committer status.
2023-11-22 16:28:03 -06:00
42c2d0f0b9 Update buildinfo.json 2023-11-22 16:21:58 -06:00
e2f732a61c Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.98 2023-11-22 18:22:49 +00:00
d53f7900d8 Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.97 2023-11-14 12:33:35 +00:00
abf3166142 Use official sha256 endpoint for update check (#477) 2023-11-11 16:34:07 +01:00
f255b89a5e Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.96 2023-11-08 12:33:25 +00:00
fd717ee1b1 Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.95 2023-11-07 15:17:59 +00:00
551b748297 Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.94 2023-10-30 18:22:14 +00:00
87403fdb1b Auto Update Factorio to stable version: 1.1.94 experimental version: 1.1.94 2023-10-30 17:15:24 +00:00
882ad42893 Auto Update Factorio to stable version: 1.1.91 experimental version: 1.1.94 2023-10-19 09:17:20 +00:00
f9c256e0e4 Auto Update Factorio to stable version: 1.1.91 experimental version: 1.1.93 2023-10-17 18:23:36 +00:00
8f0e42ec25 Auto Update Factorio to stable version: 1.1.91 experimental version: 1.1.92 2023-09-25 20:17:57 +00:00
6b92576644 Auto Update Factorio to stable version: 1.1.91 experimental version: 1.1.91 2023-09-21 11:14:14 +00:00
2f51b1ae60 Auto Update Factorio to stable version: 1.1.91 experimental version: 1.1.91 2023-09-21 10:18:47 +00:00
21fbb3f294 Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.91 2023-09-13 15:17:57 +00:00
d5e3f1580b Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.90 2023-09-07 09:16:44 +00:00
e3c1e34fe7 Removed intermediate versions 2023-08-20 11:28:02 +02:00
0fc0e18cb0 Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.89 2023-08-16 18:20:19 +00:00
d634a84e0f feat: Auto-update docker-compose.yml (#472)
Update docker-compose.yml with the latest stable version.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-06 18:55:55 +02:00
ba5670692e Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.88 2023-07-20 19:13:32 +00:00
ceea4e5dcb Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.87 2023-07-13 13:32:41 +00:00
0f5d60d61c Auto Update Factorio to stable version: 1.1.87 experimental version: 1.1.87 2023-07-13 12:40:53 +00:00
9171b1fd5d Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.87 2023-07-04 12:41:24 +00:00
ced1340b11 Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.86 2023-06-28 18:24:29 +00:00
d7e6952db8 Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.85 2023-06-16 18:20:59 +00:00
24218ec31a Update sha256 hash for 1.1.83 (#471) 2023-06-16 01:37:11 +02:00
5491f01acb Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.84 2023-06-15 10:19:08 +00:00
3e8c2f5cb7 Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.83 2023-06-14 20:17:39 +00:00
d306b82fbe Auto Update Factorio to stable version: 1.1.80 experimental version: 1.1.82 2023-05-29 00:30:09 +00:00
bd1ba3cf9d Use new version API to check update (#466)
* Use new version API
Update latest to experimental

* fix by shellcheck

* Revert "Auto Update Factorio to version:"

This reverts commit dfd442dfda.

* Fix correct exit when online information get fails
2023-05-29 02:28:58 +02:00
dfd442dfda Auto Update Factorio to version: 2023-05-12 10:18:29 +00:00
f262181b4e Update README on version update 2023-04-16 14:54:00 +02:00
f7282c516c Add --console-log support (#461) 2023-04-16 12:55:05 +02:00
4fe8b3d0bd Auto Update Factorio to version: 1.1.80 2023-04-15 11:13:25 +00:00
69e7d8ee55 bash script version watchdog (#462)
* impl version watchdog

* Update update.sh

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>

* increase update check frequency to per hour

* Update .github/workflows/update.yml

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>

* Update update.sh

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>

* Update update.sh

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>

* Update .github/workflows/update.yml

Co-authored-by: Sandro <sandro.jaeckel@gmail.com>

* prevent schedule running on fork

---------

Co-authored-by: Florian Kinder <florian.kinder@fankserver.com>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
2023-04-15 12:41:12 +02:00
d90480712d Update to Factorio version 2023-02-01 15:03:11 +00:00
d74b635be5 Update README.md (#457)
Does the same as always, except if the container was stopped. I think most user will prefer this setting.
2023-01-16 15:22:43 +01:00
0b5695e55a Update to Factorio version 2023-01-13 15:56:21 +00:00
34bf552c2c Update to Factorio version 2023-01-11 17:46:11 +00:00
bd048b90e2 Update to Factorio version 2022-12-16 15:51:09 +00:00
771eb142f0 Update to Factorio version 2022-12-06 14:31:15 +00:00
492b0378a3 Update to Factorio version 2022-12-01 18:36:13 +00:00
2ac5f259fa Update to Factorio version 2022-11-22 15:11:08 +00:00
5bf1b045e1 Update to Factorio version 2022-11-11 17:56:28 +00:00
b09c5ab001 Update to Factorio version 2022-11-04 12:11:14 +00:00
c6bf7fef1d Update to Factorio version 2022-10-27 14:06:10 +00:00
626351232a Update to Factorio version 2022-10-11 15:41:13 +00:00
db41eaad31 Update to Factorio version 2022-09-16 09:46:09 +00:00
02695f0f00 Update to Factorio version 2022-09-12 15:11:11 +00:00
5aef1b9f6f Add an IP bind param to the entrypoint (#447)
* Add an IP bind param to the entrypoint

* Add an example usage to readme

* Rename to BIND
2022-09-05 11:01:06 +02:00
2f28ee6626 Update to Factorio version 2022-08-29 09:36:17 +00:00
9912dbd9bb Update to Factorio version 2022-08-22 15:11:22 +00:00
420fecc788 Update to Factorio version 2022-08-19 13:41:12 +00:00
67bea4df99 Update to Factorio version 2022-08-19 10:16:10 +00:00
b12e652e4d Update Dockerfile - add curl retries (#444) (#445)
Adding configurable retries to the curl download of the headless server tarball.
2022-08-06 09:54:28 +02:00
d0cfb691ec Update to Factorio version 2022-08-05 13:31:10 +00:00
88757eb5d1 Update to Factorio version 2022-08-02 15:56:10 +00:00
e365e2cd5e Update to Factorio version 2022-07-28 14:01:12 +00:00
d7db07e265 Update to Factorio version 2022-07-26 12:26:10 +00:00
e5aac5fc9e Fixed typo in README.md (#442) 2022-07-12 18:10:40 +02:00
0f969e517a Update Docker Compose to 1.1.61 (#441) 2022-07-12 13:56:37 +02:00
96d38bc3e8 Update to Factorio version 2022-06-29 10:16:08 +00:00
4e43fdd73b Update to Factorio version 2022-06-23 10:51:11 +00:00
b20ff166e7 Update to Factorio version 2022-06-06 16:16:10 +00:00
e0165b4b2d Update server version in docker-compose file. (#436) 2022-05-17 16:32:41 +02:00
bbfbb86308 Update to Factorio version 2022-05-11 12:26:08 +00:00
0aae38e6a0 Update to Factorio version 2022-05-06 09:11:12 +00:00
991d3e2765 Update to Factorio version 2022-05-02 13:46:12 +00:00
e4ce42d9f3 Update to Factorio version 2022-04-01 15:21:08 +00:00
157f9484db Update to Factorio version 2022-03-31 14:41:04 +00:00
a8326cd88a Update to Factorio version 2022-03-09 15:35:18 +00:00
1ebd9ced8d Update to Factorio version 2022-02-23 16:35:18 +00:00
723160de54 Update to Factorio version 2022-02-23 16:20:15 +00:00
cc96cf2294 Update to Factorio version 2022-02-23 13:15:15 +00:00
79e22b8db5 Update to Factorio version 2022-01-21 17:45:12 +00:00
5a03444010 Update to Factorio version 2022-01-19 11:40:12 +00:00
43ce3dc8e1 Update to Factorio version 2022-01-18 17:45:12 +00:00
97e1433fde Update to Factorio version 2022-01-18 11:55:18 +00:00
f6aec0a546 Update to Factorio version 2021-12-23 16:30:15 +00:00
039a8626ba Update to Factorio version 2021-12-21 12:20:14 +00:00
634e7267a9 Update to Factorio version 2021-12-10 09:00:12 +00:00
d1e5ac742e Update to Factorio version 2021-12-07 17:35:22 +00:00
9eec6b9dd5 Update to Factorio version 2021-11-25 13:00:14 +00:00
c8b079caf0 Update to Factorio version 2021-11-24 14:50:12 +00:00
bce3ff95ba Update to Factorio version 2021-11-23 23:30:06 +00:00
faa84dbfa6 Update to Factorio version 2021-11-06 08:23:55 +00:00
8003142235 Update to Factorio version 2021-11-05 10:28:56 +00:00
9863a4cd74 Update to Factorio version 2021-10-28 14:03:56 +00:00
c5d668ac09 Update to Factorio version 2021-10-27 19:13:56 +00:00
87a4ba87e5 Update to Factorio version 2021-10-26 11:43:58 +00:00
9bdbd90322 Update to Factorio version 2021-10-13 12:33:56 +00:00
4812b5b970 Update to Factorio version 2021-10-11 11:43:56 +00:00
65e3f84c4f skip pushing to dockerhub when user and pass are not specified (#418) 2021-09-25 18:38:59 +02:00
02cc66c3ba Update to Factorio version 2021-09-24 11:43:55 +00:00
c09257d28a Update to Factorio version 2021-09-23 22:34:17 +02:00
769617edc4 Revert "Bump frolvlad/alpine-glibc from alpine-3.12 to alpine-3.14 in /docker (#410)"
This reverts commit 50d60680e0.
2021-09-13 16:35:50 +02:00
d6154359d9 support older versions of docker and docker-compose (#414) 2021-09-09 17:13:45 +02:00
765d2bb23d Fixed syntax in workflow 2021-09-09 15:11:22 +02:00
50d60680e0 Bump frolvlad/alpine-glibc from alpine-3.12 to alpine-3.14 in /docker (#410)
Bumps frolvlad/alpine-glibc from alpine-3.12 to alpine-3.14.

---
updated-dependencies:
- dependency-name: frolvlad/alpine-glibc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-08 17:12:28 +02:00
0d5f77f0da Update dependabot to check in ./docker (#405) 2021-09-08 17:10:00 +02:00
0a56912cfd Update to Factorio version 2021-09-08 17:07:22 +02:00
136329f45e Removed old travic ci badge 2021-09-02 16:36:13 +02:00
f3dc109e7e update to sha256 for checksum verification (#407)
* update sha1 to sha256 for checksum validation

* switch jinja templating to docker build-args
2021-09-02 16:01:54 +02:00
f84fee3624 Update to Factorio version 2021-09-02 15:19:47 +02:00
118f149aee Update to Factorio version 2021-09-02 15:06:37 +02:00
60165855ff Update to Factorio version 2021-09-02 15:01:17 +02:00
89b9851edb Include templating support (#382) 2021-09-02 14:57:59 +02:00
f2a5d6d075 Update to Factorio version 2021-09-02 14:40:18 +02:00
5e018ca2ae Added autogeneration tags in README.md 2021-09-02 14:40:01 +02:00
0160889854 add a section to the readme which lists the existing environment variables (#406) 2021-09-02 09:51:00 +02:00
bc9276737b Updated Readme 2021-09-02 09:48:23 +02:00
5e3943362b update to 1.1.39 (#403) 2021-09-02 09:42:03 +02:00
3778d6bb66 Factorio 1.1.38 update (#401)
Co-authored-by: server-01 <server-01@joris.biz>
2021-08-20 22:01:08 +02:00
fbf430373d update to 1.1.37 (#399) 2021-08-05 22:27:42 +02:00
a495ac72cd Replaced badge 2021-07-13 22:02:19 +02:00
17e84504cf bumb version in readme & removed microbadger badge 2021-07-13 21:57:43 +02:00
cea55cda67 Update Dockerfile to support Factorio 1.1.36 (#398)
Resolve #397 by adding Factorio 1.1.36 support

Co-authored-by: jpsenior <jp.senior@gmail.com>
2021-07-13 21:50:47 +02:00
b0ad3fa036 Update to Factorio 0.18.47 2021-06-23 15:02:49 +00:00
1a6e902c6b Update to Factorio 0.18.47 2021-06-21 15:23:33 +00:00
dadf88d5e3 Update to Factorio 0.18.47 2021-06-21 05:12:29 +00:00
b065ecb257 Update to Factorio 0.18.47 2021-06-20 18:59:25 +00:00
f0b1ff342f Update to Factorio 0.18.47 2021-06-20 13:19:09 +00:00
9a563a35b8 Update to Factorio 0.18.47 2021-06-20 08:54:29 +00:00
75543ebbe6 Update to Factorio 0.18.47 2021-06-20 02:20:10 +00:00
d17a6e648e Update to Factorio 0.18.47 2021-06-19 09:44:12 +00:00
b96fb634b1 Update to Factorio 0.18.47 2021-06-18 03:24:45 +00:00
9248c57549 Update to Factorio 0.18.47 2021-06-17 11:48:40 +00:00
8641b6d34b Update to Factorio 0.18.47 2021-06-17 11:24:07 +00:00
aefd5339c6 Update to Factorio 1.1.35 2021-06-16 16:27:58 +00:00
504aa3a05a Update to Factorio 0.18.47 2021-06-16 10:58:07 +00:00
ccc7f5624a Update to Factorio 0.18.47 2021-06-16 10:55:45 +00:00
0336fbe3cf Update to Factorio 0.18.47 2021-06-16 10:33:27 +00:00
452aab7ffb Update to Factorio 0.18.47 2021-06-16 10:08:06 +00:00
a953759b96 Update to Factorio 0.18.47 2021-06-16 10:06:42 +00:00
f61abdc8b5 Update to Factorio 0.18.47 2021-06-16 09:44:42 +00:00
bb4d2d0154 Update to Factorio 0.18.47 2021-06-16 09:41:34 +00:00
f44f690b6a Update to Factorio 0.18.47 2021-06-16 01:12:34 +00:00
eadada76b9 Update to Factorio 0.18.47 2021-06-15 18:25:45 +00:00
45eb323d17 Update to Factorio 0.18.47 2021-06-15 16:45:41 +00:00
cad67f5d0b Update to Factorio 0.18.47 2021-06-15 15:45:43 +00:00
18fe336fb8 Update to Factorio 0.18.47 2021-06-15 15:30:50 +00:00
a7c9b3e1c8 Update to Factorio 0.18.47 2021-06-15 10:55:53 +00:00
2026cce01a Update to Factorio 0.18.47 2021-06-14 12:36:38 +00:00
7b7f47f464 Update to Factorio 0.18.47 2021-06-14 05:24:13 +00:00
1f83234834 Update to Factorio 0.18.47 2021-06-13 20:46:18 +00:00
bc06b94f38 Update to Factorio 0.18.47 2021-06-12 12:11:20 +00:00
3abd2d69fc Update to Factorio 0.18.47 2021-06-12 08:31:41 +00:00
63fc1066dc Update to Factorio 0.18.47 2021-06-12 03:56:47 +00:00
7f4e005b1a Update to Factorio 0.18.47 2021-06-10 21:29:54 +00:00
5222d392b1 Update to Factorio 0.18.47 2021-06-10 12:21:32 +00:00
be8c1b28a3 Update to Factorio 0.18.47 2021-06-08 16:45:37 +00:00
e5a70d4ada Update to Factorio 0.18.47 2021-06-06 21:30:20 +00:00
31448a0c06 Update to Factorio 0.18.47 2021-06-06 17:37:22 +00:00
6d2fcd5696 Update to Factorio 0.18.47 2021-06-06 16:22:33 +00:00
65b909310c Update to Factorio 0.18.47 2021-06-06 13:05:51 +00:00
e8fca26f7a Update to Factorio 0.18.47 2021-06-06 11:55:03 +00:00
6ce248eacb Update to Factorio 0.18.47 2021-06-05 14:06:06 +00:00
a683f67f86 Update to Factorio 0.18.47 2021-06-05 10:06:28 +00:00
b253a086cc Update to Factorio 0.18.47 2021-06-04 10:35:23 +00:00
36ecbb3de8 Update to Factorio 0.18.47 2021-06-01 05:54:15 +00:00
3bd6929ee7 Update to Factorio 0.18.47 2021-05-31 05:28:27 +00:00
cb4f36fc91 Update to Factorio 0.18.47 2021-05-27 07:11:10 +00:00
06433d2ba1 Update to Factorio 0.18.47 2021-05-26 15:15:43 +00:00
31a0c78ba6 Update to Factorio 0.18.47 2021-05-26 13:08:55 +00:00
29f5222c35 Update to Factorio 0.18.47 2021-05-25 17:24:50 +00:00
13ebf33867 Update to Factorio 0.18.47 2021-05-24 13:21:35 +00:00
3947458623 Update to Factorio 1.1.34 2021-05-24 11:46:29 +00:00
cb6eb6e519 Update to Factorio 0.18.47 2021-05-24 06:38:10 +00:00
9896b03e0a Update to Factorio 0.18.47 2021-05-23 21:50:10 +00:00
5176be56db Update to Factorio 0.18.47 2021-05-23 21:19:31 +00:00
72fdb9fc42 Update to Factorio 0.18.47 2021-05-23 07:17:00 +00:00
b0b62d5ba7 Update to Factorio 0.18.47 2021-05-20 22:11:42 +00:00
4f73862221 Update to Factorio 0.18.47 2021-05-19 17:37:45 +00:00
5b83699e5c Update to Factorio 0.18.47 2021-05-15 10:46:54 +00:00
511520c459 Update to Factorio 0.18.47 2021-05-15 07:23:50 +00:00
99db93d6f8 Update to Factorio 0.18.47 2021-05-14 22:43:13 +00:00
24825309c3 Update to Factorio 0.18.47 2021-05-14 22:18:14 +00:00
db25aab203 Update to Factorio 0.18.47 2021-05-14 22:08:13 +00:00
d10ec1e309 Update to Factorio 0.18.47 2021-05-13 23:04:53 +00:00
14851be061 Update to Factorio 0.18.47 2021-05-13 22:53:34 +00:00
1212e00fa3 Update to Factorio 0.18.47 2021-05-11 12:31:29 +00:00
c537410871 Update to Factorio 0.18.47 2021-05-11 01:01:33 +00:00
068b96ae2b Update to Factorio 0.18.47 2021-05-06 07:08:36 +00:00
9c3ec3c817 Update to Factorio 0.18.47 2021-05-04 13:36:13 +00:00
229f3d7fda Update to Factorio 0.18.47 2021-05-04 10:42:44 +00:00
248dab3db1 Update to Factorio 0.18.47 2021-05-04 10:22:59 +00:00
c25e2c8a1d Disable 0.18 because it got yanked from the download servers 2021-05-03 19:04:50 +02:00
70 changed files with 2325 additions and 3950 deletions

View File

@ -1,27 +1,11 @@
version: 2
updates:
- package-ecosystem: docker
directory: "/0.18"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/0.17"
interval: "daily"
- package-ecosystem: docker
directory: "/docker"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/0.16"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/0.15"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/0.14"
schedule:
interval: daily
open-pull-requests-limit: 10
interval: "daily"

29
.github/workflows/docker-build.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Docker build & push
on:
push:
branches:
- master
paths:
- buildinfo.json
# workaround for #526
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: build and push
if: ${{ env.DOCKER_USERNAME != '' && env.DOCKER_PASSWORD != '' }}
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
./build.py --push-tags --multiarch

View File

@ -1,17 +1,27 @@
name: Docker build & push
name: Docker Hub Description
on:
push:
branches: master
branches:
- master
paths:
- README.md
# workaround for #526
workflow_dispatch:
jobs:
docker-description:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v2.4.1
uses: peter-evans/dockerhub-description@v4.0.2
if: ${{ env.DOCKER_USERNAME != '' && env.DOCKER_PASSWORD != '' }}
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

View File

@ -1,53 +0,0 @@
name: Docker build & push
on:
pull_request:
push:
branches: master
tags:
- '*'
jobs:
old-version:
runs-on: ubuntu-latest
strategy:
matrix:
version: [ "1.0", "0.18", "0.17", "0.16", "0.15", "0.14" ]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: build
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
VERSION_SHORT: ${{ matrix.version }}
run: |
./build.sh ${{ matrix.version }}
stable:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: build
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
EXTRA_TAG: stable,latest
VERSION_SHORT: "1.1"
run: |
./build.sh $VERSION_SHORT
# experimental:
# runs-on: ubuntu-latest
# steps:
# - name: Checkout
# uses: actions/checkout@v2
# - name: build
# env:
# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
# EXTRA_TAG: latest
# VERSION_SHORT: "1.2"
# run: |
# ./build.sh $VERSION_SHORT

View File

@ -3,13 +3,16 @@ name: 'Linter'
on:
pull_request:
push:
branches: master
branches:
- master
jobs:
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
- name: shellcheck
uses: reviewdog/action-shellcheck@v1
with:
@ -19,7 +22,9 @@ jobs:
hadolint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
- name: hadolint
uses: reviewdog/action-hadolint@v1
with:

21
.github/workflows/update.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Check Update
on:
schedule:
- cron: "0 * * * *"
workflow_dispatch:
jobs:
check:
runs-on: ubuntu-latest
if: github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository == 'factoriotools/factorio-docker')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.REPO_TOKEN }}
- name: Run update script
run: ./update.sh
shell: bash

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# IDE
.idea

View File

@ -1,26 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.13
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ENV VERSION=0.14.23 \
SHA1=6ef84341c6fc1cf45cfdd6acc8468aaa117b9e8a
RUN mkdir -p /opt \
&& apk --no-cache add curl tini pwgen \
&& curl -sSL https://www.factorio.com/get-download/$VERSION/headless/linux64 \
-o /tmp/factorio_headless_x64_$VERSION.tar.gz \
&& echo "$SHA1 /tmp/factorio_headless_x64_$VERSION.tar.gz" | sha1sum -c \
&& tar xzf /tmp/factorio_headless_x64_$VERSION.tar.gz --directory /opt \
&& rm /tmp/factorio_headless_x64_$VERSION.tar.gz \
&& apk del curl \
&& ln -s /factorio/saves /opt/factorio/saves \
&& ln -s /factorio/mods /opt/factorio/mods
VOLUME /factorio
EXPOSE 34197/udp 27015/tcp
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/docker-entrypoint.sh"]

View File

@ -1,2 +0,0 @@
#!/bin/sh
sudo docker build --no-cache -t factorio .

View File

@ -1,2 +0,0 @@
#!/bin/sh
sudo rm -rf /tmp/factorio

View File

@ -1,35 +0,0 @@
#!/bin/sh -x
set -euo pipefail
SAVES=/factorio/saves
CONFIG=/factorio/config
mkdir -p "$SAVES"
mkdir -p /factorio/mods
mkdir -p "$CONFIG"
if [ ! -f $CONFIG/rconpw ]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [ ! -f "$CONFIG/server-settings.json" ]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [ ! -f "$CONFIG/map-gen-settings.json" ]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if ! find -L "$SAVES" -iname \*.zip -mindepth 1 -print | grep -q .; then
/opt/factorio/bin/x64/factorio \
--create "$SAVES/_autosave1.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port 34197 \
--start-server-load-latest \
--server-settings "$CONFIG/server-settings.json" \
--rcon-port 27015 \
--rcon-password "$(cat "$CONFIG/rconpw")"

View File

@ -1,6 +0,0 @@
#!/bin/sh
sudo docker run --rm -it \
-v /tmp/factorio:/factorio \
--name factorio \
factorio "$@"
find /tmp/factorio -type f

View File

@ -1,30 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.13
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=0.15.40 \
SHA1=f79a975f6b8c0ee87e2fa60f7d1f7133f332c3ec
RUN mkdir -p /opt \
&& apk add --update --no-cache tini pwgen \
&& apk add --update --no-cache --virtual .build-deps curl \
&& curl -sSL https://www.factorio.com/get-download/$VERSION/headless/linux64 \
-o /tmp/factorio_headless_x64_$VERSION.tar.xz \
&& echo "$SHA1 /tmp/factorio_headless_x64_$VERSION.tar.xz" | sha1sum -c \
&& tar xf /tmp/factorio_headless_x64_$VERSION.tar.xz --directory /opt \
&& chmod -R ugo=rwx /opt/factorio \
&& rm /tmp/factorio_headless_x64_$VERSION.tar.xz \
&& ln -s /factorio/saves /opt/factorio/saves \
&& ln -s /factorio/mods /opt/factorio/mods \
&& apk del .build-deps
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/docker-entrypoint.sh"]

View File

@ -1,8 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197"
volumes:
- /tmp/factorio:/factorio

View File

@ -1,43 +0,0 @@
#!/bin/sh -x
set -euo pipefail
SAVES=/factorio/saves
CONFIG=/factorio/config
mkdir -p "$SAVES"
mkdir -p /factorio/mods
mkdir -p "$CONFIG"
if [ ! -f "$CONFIG/rconpw" ]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [ ! -f "$CONFIG/server-settings.json" ]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [ ! -f "$CONFIG/map-gen-settings.json" ]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [ ! -f "$CONFIG/map-settings.json" ]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
if ! find -L "$SAVES" -iname \*.zip -mindepth 1 -print | grep -q .; then
/opt/factorio/bin/x64/factorio \
--create "$SAVES/_autosave1.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-latest \
--server-settings "$CONFIG/server-settings.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json

View File

@ -1,46 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.13
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=0.16.51 \
SHA1=127e7ff484ab263b13615d6114013ce0a66ac929 \
SAVES=/factorio/saves \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID"
RUN mkdir -p /opt /factorio \
&& apk add --update --no-cache pwgen su-exec shadow \
&& apk add --update --no-cache --virtual .build-deps curl \
&& curl -sSL https://www.factorio.com/get-download/$VERSION/headless/linux64 \
-o /tmp/factorio_headless_x64_$VERSION.tar.xz \
&& echo "$SHA1 /tmp/factorio_headless_x64_$VERSION.tar.xz" | sha1sum -c \
&& tar xf /tmp/factorio_headless_x64_$VERSION.tar.xz --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm /tmp/factorio_headless_x64_$VERSION.tar.xz \
&& ln -s $SAVES /opt/factorio/saves \
&& ln -s $MODS /opt/factorio/mods \
&& ln -s $SCENARIOS /opt/factorio/scenarios \
&& ln -s $SCRIPTOUTPUT /opt/factorio/script-output \
&& apk del .build-deps \
&& addgroup -g $PGID -S $GROUP \
&& adduser -u $PUID -G $GROUP -s /bin/sh -SDH $USER \
&& chown -R $USER:$GROUP /opt/factorio /factorio
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
COPY files/ /
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,9 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio

View File

@ -1,62 +0,0 @@
#!/bin/sh -x
set -euo pipefail
id
FACTORIO_VOL=/factorio
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
mkdir -p "$SCRIPTOUTPUT"
if [ ! -f "$CONFIG/rconpw" ]; then
pwgen 15 1>"$CONFIG/rconpw"
fi
if [ ! -f "$CONFIG/server-settings.json" ]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [ ! -f "$CONFIG/map-gen-settings.json" ]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [ ! -f "$CONFIG/map-settings.json" ]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
if find -L "$SAVES" -iname \*.tmp.zip -mindepth 1 -print | grep -q .; then
rm -f "$SAVES"/*.tmp.zip
fi
if [ "$(id -u)" = '0' ]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
fi
if ! find -L "$SAVES" -iname \*.zip -mindepth 1 -print | grep -q .; then
$SU_EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/_autosave1.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
$SU_EXEC /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-latest \
--server-settings "$CONFIG/server-settings.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json \
"$@"

View File

@ -1,42 +0,0 @@
#!/bin/sh -x
if [ -z "$1" ]; then
echo "No argument supplied"
fi
SERVER_SCENARIO=$1
set -euo pipefail
id
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
#chown -R factorio /factorio
if [ ! -f "$CONFIG/rconpw" ]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [ ! -f "$CONFIG/server-settings.json" ]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [ ! -f "$CONFIG/map-gen-settings.json" ]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [ ! -f "$CONFIG/map-settings.json" ]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-scenario "$SERVER_SCENARIO" \
--server-settings "$CONFIG/server-settings.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json

View File

@ -1,29 +0,0 @@
#!/bin/sh -x
if [ -z "$1" ]; then
echo "No argument supplied"
fi
SERVER_SCENARIO=$1
set -euo pipefail
id
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
if [ ! -f "$CONFIG/server-settings.json" ]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [ ! -f "$CONFIG/map-gen-settings.json" ]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [ ! -f "$CONFIG/map-settings.json" ]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--scenario2map "$SERVER_SCENARIO"

View File

@ -1,45 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.13
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=0.17.79 \
SHA1=7f127baf3cf01c6e545a9ca376dec1ac37468f8a \
SAVES=/factorio/saves \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID"
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN set -ox pipefail \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& apk add --update --no-cache --no-progress bash binutils curl file gettext jq libintl pwgen shadow su-exec \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" \
&& echo "$SHA1 $archive" | sha1sum -c \
|| (sha1sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
&& addgroup -g "$PGID" -S "$GROUP" \
&& adduser -u "$PUID" -G "$GROUP" -s /bin/sh -SDH "$USER" \
&& chown -R "$USER":"$GROUP" /opt/factorio /factorio
COPY files/*.sh /
COPY files/config.ini /opt/factorio/config/config.ini
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,15 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio
# environment:
# - PUID=1000
# - PGID=1000
# - UPDATE_MODS_ON_START=true
# - USERNAME=FactorioUsername
# - TOKEN=FactorioToken

View File

@ -1,714 +0,0 @@
; version=5
; This is INI file : https://en.wikipedia.org/wiki/INI_file#Format
; Semicolons (;) at the beginning of the line indicate a comment. Comment lines are ignored.
[path]
read-data=__PATH__executable__/../../data
write-data=__PATH__executable__/../..
[general]
locale=
[other]
; Options: true, false
; verbose-logging=false
; Options: true, false
; log-saving-statistics=false
; autosave-interval=5
; autosave-slots=3
; In ticks
; minimum-latency-in-multiplayer=0
; In seconds
; multiplayer-initial-connection-timeout=10
; port=34197
; max-map-preview-chunk-side=64
; max-map-preview-threads=7
; In bytes
; max-multiplayer-script-reload-size=1048576
; Options: true, false
; enable-steam-networking=true
; proxy=
; proxy-username=
; proxy-password=
; Options: true, false
; check-updates=true
; Options: true, false
; enable-experimental-updates=false
; Options: true, false
; enable-new-mods=true
; Options: true, false
; use-mod-settings-per-save=true
; Options: true, false
; disable-minimal-mode=false
; Options: true, false
; disable-blueprint-storage=false
; Disables tracking which mod created/changed what prototype. Mainly for faster startup during development.
;
; Options: true, false
; disable-prototype-history=false
; Print a warning for all prototype values that were not accessed.
;
; Options: true, false
; check-unused-prototype-data=false
; Options: true, false
; enable-razer-chroma-support=true
; Options: true, false
; enable-logitech-led-support=true
; Options: true, false
; enable-crash-log-uploading=true
; Options: true, false
; enable-heap-validation=true
; Options: true, false
; enable-threaded-message-pump=true
; Options: true, false
; enable-taskbar-animation=true
; Does nothing on Windows
;
; Options: true, false
; non-blocking-saving=false
; Related to MacOS
;
; Options: true, false
; discard-mouse-events-when-accessibility-zoomed=false
; Options: true, false
; enable-blueprint-storage-cloud-sync=false
; Options: fast, maximum
; multiplayer-compression-level=fast
; Options: none, fast, maximum
; autosave-compression-level=fast
; Socket to host RCON on when lauching MP server from the menu.
; local-rcon-socket=0.0.0.0:0
; Password for RCON when launching MP server from the menu.
; local-rcon-password=
[interface]
; Options: true, false
; automatic-ui-scale=true
; custom-ui-scale=1.000000
; tooltip-delay=0.040000
; entity-tooltip-delay=0.000000
; tooltip-offset=20
; output-console-delay=1200
; train-stop-label-angle=0.085526
; active-quick-bars=2
; shortcut-bar-rows=2
; Options: true, false
; force-default-logistic-filter-count-to-one=false
; Options: true, false
; autosort-inventory=true
; Options: true, false
; research-finished-stops-game=false
; Options: true, false
; use-item-groups=true
; Options: true, false
; use-item-subgroups=true
; Options: true, false
; use-version-filter-in-browse-games-gui=true
; Options: true, false
; use-version-filter-in-install-mods-gui=true
; Options: true, false
; play-sound-for-chat-messages=true
; Options: true, false
; fuzzy-search-enabled=false
; Options: true, false
; pick-ghost-cursor=false
; Options: true, false
; show-minimap=true
; Options: true, false
; show-tips-and-tricks=true
; Options: true, false
; show-tutorial-notifications=true
; Options: true, false
; show-turret-radius-when-blueprinting=false
; Options: true, false
; show-item-labels-in-cursor=true
; Options: true, false
; show-rail-block-visualization=true
; Options: true, false
; show-missing-logistic-network-icon=true
; Options: true, false
; show-interaction-indications=true
; Options: true, false
; show-grid-when-paused=true
; Options: true, false
; show-inserter-arrows-when-selected=true
; Options: true, false
; show-inserter-arrows-when-detailed-info-is-on=false
; Options: true, false
; show-pump-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-mining-drill-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-combinator-settings-when-detailed-info-is-on=false
; Options: true, false
; entity-tooltip-on-the-side=true
; Options: true, false
; show-mod-owners-in-tooltips=true
; Options: true, false
; show-descriptions-in-tooltips=true
; Options: true, false
; show-total-raw-in-recipe-tooltips=true
; debug-font-size=18
; train-visualization-length=5
[sound]
; master-volume=0.600000
; music-volume=0.400000
; game-effects-volume=0.700000
; gui-effects-volume=0.700000
; walking-sound-volume=0.300000
; environment-sounds-volume=0.450000
; alerts-volume=0.550000
; wind-volume=0.400000
; audible-distance=40.000000
; environment-audible-distance=15.000000
; maximum-environment-sounds=15
; active-gui-volume-modifier=1.000000
; active-gui-environment-volume-modifier=0.600000
; ambient-music-pause-mean-seconds=45.000000
; ambient-music-pause-variance-seconds=30.000000
; Options: main-tracks-only, interleave-main-tracks-with-interludes, randomize-all
; ambient-music-mode=interleave-main-tracks-with-interludes
; zoom-audible-distance-coefficient=1.000000
; zoom-volume-coefficient=2.000000
[map-view]
; Options: true, false
; show-logistic-network=false
; Options: true, false
; show-electric-network=false
; Options: true, false
; show-turret-range=false
; Options: true, false
; show-pollution=true
; Options: true, false
; show-networkless-logistic-members=false
; Options: true, false
; show-train-station-names=true
; Options: true, false
; show-player-names=true
; Options: true, false
; show-non-standard-map-info=false
[debug]
; force=enemy
; Options: true, false
; capture-perf-statistics=false
; Options: always, debug, never
; show-fps=debug
; Options: always, debug, never
; show-detailed-info=debug
; Options: always, debug, never
; show-time-usage=debug
; Options: always, debug, never
; show-gpu-time-usage=debug
; Options: always, debug, never
; show-sprite-counts=never
; Options: always, debug, never
; show-lua-object-statistics=never
; Options: always, debug, never
; show-multiplayer-waiting-icon=debug
; Options: always, debug, never
; show-multiplayer-statistics=debug
; Options: always, debug, never
; show-multiplayer-selection-rectangles=never
; Options: always, debug, never
; show-debug-info-in-tooltips=debug
; Options: always, debug, never
; hide-mod-guis=never
; Options: always, debug, never
; show-tile-grid=never
; Options: always, debug, never
; show-collision-rectangles=never
; Options: always, debug, never
; show-selection-rectangles=never
; Options: always, debug, never
; show-render-rectangles=never
; Options: always, debug, never
; show-entity-positions=never
; Options: always, debug, never
; show-entity-velocities=never
; Options: always, debug, never
; show-selected-entity-advanced-tiles=never
; Options: always, debug, never
; show-selected-input-transport-belts=never
; Options: always, debug, never
; show-paths=never
; Options: always, debug, never
; show-path-requests=never
; Options: always, debug, never
; show-next-waypoint-bb=never
; Options: always, debug, never
; show-target=never
; Options: always, debug, never
; show-unit-group-info=never
; Options: always, debug, never
; show-unit-behavior-info=never
; Options: always, debug, never
; show-pathfinder-fringe=never
; Options: always, debug, never
; show-path-cache=never
; Options: always, debug, never
; show-path-cache-paths=never
; Options: always, debug, never
; show-rail-paths=never
; Options: always, debug, never
; show-rolling-stock-count=never
; Options: always, debug, never
; show-rail-connections=never
; Options: always, debug, never
; show-rail-joints=never
; Options: always, debug, never
; show-rail-signal-states=never
; Options: always, debug, never
; show-rail-segment-collision-boxes=never
; Options: always, debug, never
; show-train-stop-point=never
; Options: always, debug, never
; show-train-braking-distance=never
; Options: always, debug, never
; show-train-signals=never
; Options: always, debug, never
; show-train-repathing=never
; Options: always, debug, never
; show-network-connected-entities=never
; Options: always, debug, never
; show-circuit-network-numbers=never
; Options: always, debug, never
; show-energy-sources-networks=never
; Options: always, debug, never
; show-active-state=never
; Options: always, debug, never
; show-wakeup-lists=never
; Options: always, debug, never
; show-transport-lines=never
; Options: always, debug, never
; show-transport-line-gaps=never
; Options: always, debug, never
; show-pollution-values=never
; Options: always, debug, never
; show-active-entities-on-chunk-counts=never
; Options: always, debug, never
; show-active-chunks=never
; Options: always, debug, never
; show-polluted-chunks=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunks=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunk-values=never
; Options: always, debug, never
; show-bad-attack-chunks=never
; Options: always, debug, never
; show-tile-variations=never
; Options: always, debug, never
; show-raw-tile-transitions=never
; Options: always, debug, never
; show-fluid-box-fluid-info=never
; Options: always, debug, never
; show-environment-sound-info=never
; Options: always, debug, never
; show-logistic-robot-targets=never
; Options: always, debug, never
; show-logistic-robots-on-map=never
; Options: always, debug, never
; show-recipe-icons-on-map=never
; Options: always, debug, never
; show-player-robots=never
; Options: always, debug, never
; show-fire-info=never
; Options: always, debug, never
; show-sticker-info=never
; Options: always, debug, never
; show-decorative-names=never
; Options: always, debug, never
; show-decorative-collision-rectangles=never
; Options: always, debug, never
; allow-increased-zoom=never
; Options: always, debug, never
; show-chunk-components=never
[multiplayer-lobby]
; name=
; description=
; Options: true, false
; visibility-public=true
; Options: true, false
; visibility-steam=true
; Options: true, false
; visibility-lan=true
; max-players=0
; Options: true, false
; ignore-player-limit-when-returning=false
; max-upload-in-kilobytes-per-second=0
; max-upload-slots=5
; password=
; tag-list=
; afk-auto-kick=0
; Options: true, false, admins-only
; allowed-commands=admins-only
; Options: true, false
; only-admins-can-pause=true
; Options: true, false
; autosave-only-on-server=true
; Options: true, false
; non-blocking-saving=true
; Options: true, false
; verify-user-identity=true
; Options: true, false
; enable-whitelist=false
[graphics]
; lights-render-quality=0.250000
; Default preferred display index should force finding primary monitor
; preferred-display-index=255
; screenshots-threads-count=8
; cache-sprite-atlas-count=1
; Options: true, false
; cache-sprite-atlas=false
; Options: true, false
; compress-sprite-atlas-cache=false
; Options: true, false
; texture-streaming=true
; streamed-atlas-physical-vram-size=0
; sprite-vertex-buffer-size=1048576
; max-texture-size=0
; max-threads=8
; 'low' and 'very-low' options are deprecated and will be migrated to 'normal'
;
; Options: high, normal, low, very-low
; graphics-quality=normal
; Options: true, false
; full-screen=true
; Options: true, false
; minimize-on-focus-loss=false
; Options: true, false
; show-smoke=true
; Options: true, false
; show-clouds=true
; Options: true, false
; show-decoratives=true
; Options: true, false
; show-item-shadows=true
; Options: true, false
; show-inserter-shadows=true
; Options: true, false
; force-opengl=false
; Options: true, false
; v-sync=true
; Options: true, false
; high-quality-animations=true
; Options: true, false
; high-quality-shadows=false
; Options: true, false
; high-quality-terrain=true
; Minimum number of turrets required to turn on the turret range overdraw optimization
; turret-overdraw-minimum-count=4
; Scale at which the turret range overdraw optimization will start being applied
; turret-overdraw-scale-threshold=0.200000
; Options: true, false
; skip-vram-detection=false
; Options: true, false
; halt-rendering-when-minimized=true
; Options: true, false
; runtime-sprite-reload=false
; Options: true, false
; full-color-depth=true
; Options: true, false
; render-in-native-resolution=true
; Options: true, false
; use-flip-presentation-model=false
; Options: true, false
; debug-api=false
; Options: true, false
; discard-buffers-on-begin-frame=true
; Options: all, high, medium, low
; video-memory-usage=high
; Options: none, high-quality, low-quality
; texture-compression-level=high-quality
; Options: true, false
; compress-virtual-atlas=true
; Options: copy, copy-sequential, flip, flip-discard
; dxgi-presentation-model=copy
; Options: none, flush, wait-for-vblank, flush-and-wait-for-vblank
; dxgi-action-before-present=none
; relevant only for flip presentation models
;
; Options: true, false
; dxgi-allow-tearing=false
; Options: false, true, auto
; dxgi-flip-do-not-wait=false
; Options: true, false
; dxgi-present-restart=false
; dxgi-swap-chain-buffer-count=0
; dxgi-max-frame-latency=0
; dxgi-adapter-index=-1
; max-sprite-loading-threads=32
; Options: true, false
; gpu-accelerated-compression=true
; Options: true, false
; gpu-accelerated-mipmap-compression=true
; Options: true, false
; wait-until-mipmap-generation-finished=true
; Options: true, false
; check-for-unused-pixels=false
; ogl-depth-buffer-bit-depth=0
; Options: false, true, auto
; ogl-accelerated-renderer=auto
; Options: true, false
; ogl-double-buffered=true
; Set to true if mipmapped sprites render very blurry on your GPU. Limited support.
;
; Options: true, false
; legacy-gpu-no-mipmaps=false
; Options: true, false
; force-linear-magnification=false
; Options: true, false
; custom-mipmap-workaround=false
; Options: true, false
; buffer-rename-workaround=false
; Comma separated list of OpenGL extensions that should not be used (for example: ARB_copy_image,KHR_debug)
; disabled-opengl-extensions=

View File

@ -1,44 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
#chown -R factorio /factorio
if [[ ! -f $CONFIG/rconpw ]]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-scenario "$SERVER_SCENARIO" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json

View File

@ -1,96 +0,0 @@
#!/bin/bash
set -eou pipefail
FACTORIO_VERSION=$1
MOD_DIR=$2
USERNAME=$3
TOKEN=$4
MOD_BASE_URL="https://mods.factorio.com"
print_step()
{
echo "$1"
}
print_success()
{
echo "$1"
}
print_failure()
{
echo "$1"
}
update_mod()
{
MOD_NAME="$1"
MOD_NAME_ENCODED="${1// /%20}"
print_step "Checking for update of mod $MOD_NAME..."
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED"
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
print_success " Custom mod not on $MOD_BASE_URL, skipped."
return 0
fi
MOD_INFO=$(echo "$MOD_INFO_JSON" | jq -j --arg version "$FACTORIO_VERSION" ".releases|reverse|map(select(.info_json.factorio_version as \$mod_version | \$version | startswith(\$mod_version)))[0]|.file_name, \";\", .download_url, \";\", .sha1")
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
if [[ $MOD_FILENAME == null ]]; then
print_failure " Not compatible with version"
return 0
fi
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Already up-to-date."
return 0
fi
print_step "Downloading..."
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
if [[ $HTTP_STATUS != 200 ]]; then
print_failure " Download failed: Code $HTTP_STATUS."
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
print_failure " Downloaded file missing!"
return 1
fi
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
print_failure " SHA1 mismatch!"
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
print_success " Download complete."
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Deleting old version: $file"
rm -f "$file"
fi
done
return 0
}
if [[ -f $MOD_DIR/mod-list.json ]]; then
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
if [[ $mod != base ]]; then
update_mod "$mod"
fi
done
fi

View File

@ -1,45 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.13
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=0.18.47 \
SHA1=f63c5e06ee9a2ec51703ad77467c4cbcccde36c6 \
SAVES=/factorio/saves \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID"
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN set -ox pipefail \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& apk add --update --no-cache --no-progress bash binutils curl file gettext jq libintl pwgen shadow su-exec \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" \
&& echo "$SHA1 $archive" | sha1sum -c \
|| (sha1sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
&& addgroup -g "$PGID" -S "$GROUP" \
&& adduser -u "$PUID" -G "$GROUP" -s /bin/sh -SDH "$USER" \
&& chown -R "$USER":"$GROUP" /opt/factorio /factorio
COPY files/*.sh /
COPY files/config.ini /opt/factorio/config/config.ini
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,15 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio
# environment:
# - PUID=1000
# - PGID=1000
# - UPDATE_MODS_ON_START=true
# - USERNAME=FactorioUsername
# - TOKEN=FactorioToken

View File

@ -1,98 +0,0 @@
#!/bin/bash
set -eoux pipefail
FACTORIO_VOL=/factorio
LOAD_LATEST_SAVE="${LOAD_LATEST_SAVE:-true}"
GENERATE_NEW_SAVE="${GENERATE_NEW_SAVE:-false}"
SAVE_NAME="${SAVE_NAME:-""}"
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
mkdir -p "$SCRIPTOUTPUT"
if [[ ! -f $CONFIG/rconpw ]]; then
# Generate a new RCON password if none exists
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
# Copy default settings if server-settings.json doesn't exist
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
NRTMPSAVES=$( find -L "$SAVES" -iname \*.tmp.zip -mindepth 1 | wc -l )
if [[ $NRTMPSAVES -gt 0 ]]; then
# Delete incomplete saves (such as after a forced exit)
rm -f "$SAVES"/*.tmp.zip
fi
if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
fi
if [[ $(id -u) = 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
fi
sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
NRSAVES=$(find -L "$SAVES" -iname \*.zip -mindepth 1 | wc -l)
if [[ $GENERATE_NEW_SAVE != true && $NRSAVES == 0 ]]; then
GENERATE_NEW_SAVE=true
SAVE_NAME=_autosave1
fi
if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -z "$SAVE_NAME" ]]; then
echo "If \$GENERATE_NEW_SAVE is true, you must specify \$SAVE_NAME"
exit 1
fi
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
fi
FLAGS=(\
--port "$PORT" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-port "$RCON_PORT" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json \
)
if [[ $LOAD_LATEST_SAVE == true ]]; then
FLAGS+=( --start-server-load-latest )
else
FLAGS+=( --start-server "$SAVE_NAME" )
fi
# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"

View File

@ -1,28 +0,0 @@
#!/bin/bash
set -eou pipefail
if [[ -f /run/secrets/username ]]; then
USERNAME=$(cat /run/secrets/username)
fi
if [[ -f /run/secrets/token ]]; then
TOKEN=$(cat /run/secrets/token)
fi
if [[ -z ${USERNAME:-} ]]; then
USERNAME="$(jq -j ".username" "$CONFIG/server-settings.json")"
fi
if [[ -z ${TOKEN:-} ]]; then
TOKEN="$(jq -j ".token" "$CONFIG/server-settings.json")"
fi
if [[ -z ${USERNAME:-} ]]; then
echo "You need to provide your Factorio username to update mods."
fi
if [[ -z ${TOKEN:-} ]]; then
echo "You need to provide your Factorio token to update mods."
fi
./update-mods.sh "$VERSION" "$MODS" "$USERNAME" "$TOKEN"

View File

@ -1,44 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
#chown -R factorio /factorio
if [[ ! -f $CONFIG/rconpw ]]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-scenario "$SERVER_SCENARIO" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json

View File

@ -1,27 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--scenario2map "$SERVER_SCENARIO"

View File

@ -1,96 +0,0 @@
#!/bin/bash
set -eou pipefail
FACTORIO_VERSION=$1
MOD_DIR=$2
USERNAME=$3
TOKEN=$4
MOD_BASE_URL="https://mods.factorio.com"
print_step()
{
echo "$1"
}
print_success()
{
echo "$1"
}
print_failure()
{
echo "$1"
}
update_mod()
{
MOD_NAME="$1"
MOD_NAME_ENCODED="${1// /%20}"
print_step "Checking for update of mod $MOD_NAME..."
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED"
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
print_success " Custom mod not on $MOD_BASE_URL, skipped."
return 0
fi
MOD_INFO=$(echo "$MOD_INFO_JSON" | jq -j --arg version "$FACTORIO_VERSION" ".releases|reverse|map(select(.info_json.factorio_version as \$mod_version | \$version | startswith(\$mod_version)))[0]|.file_name, \";\", .download_url, \";\", .sha1")
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
if [[ $MOD_FILENAME == null ]]; then
print_failure " Not compatible with version"
return 0
fi
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Already up-to-date."
return 0
fi
print_step "Downloading..."
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
if [[ $HTTP_STATUS != 200 ]]; then
print_failure " Download failed: Code $HTTP_STATUS."
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
print_failure " Downloaded file missing!"
return 1
fi
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
print_failure " SHA1 mismatch!"
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
print_success " Download complete."
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Deleting old version: $file"
rm -f "$file"
fi
done
return 0
}
if [[ -f $MOD_DIR/mod-list.json ]]; then
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
if [[ $mod != base ]]; then
update_mod "$mod"
fi
done
fi

View File

@ -1,45 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.12
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=1.0.0 \
SHA1=a50dd6f1ab17acde5a8d77bc5fb478c798d9c20e \
SAVES=/factorio/saves \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID"
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN set -ox pipefail \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& apk add --update --no-cache --no-progress bash binutils curl file gettext jq libintl pwgen shadow su-exec \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" \
&& echo "$SHA1 $archive" | sha1sum -c \
|| (sha1sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
&& addgroup -g "$PGID" -S "$GROUP" \
&& adduser -u "$PUID" -G "$GROUP" -s /bin/sh -SDH "$USER" \
&& chown -R "$USER":"$GROUP" /opt/factorio /factorio
COPY files/*.sh /
COPY files/config.ini /opt/factorio/config/config.ini
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,16 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio
# environment:
# - PUID=1000
# - PGID=1000
# - UPDATE_MODS_ON_START=true
# - USERNAME=FactorioUsername
# - TOKEN=FactorioToken
# - PORT=34198

View File

@ -1,755 +0,0 @@
; version=8
; This is INI file : https://en.wikipedia.org/wiki/INI_file#Format
; Semicolons (;) at the beginning of the line indicate a comment. Comment lines are ignored.
[path]
read-data=__PATH__executable__/../../data
write-data=__PATH__executable__/../..
[general]
locale=
[other]
; Options: true, false
; verbose-logging=false
; Options: true, false
; log-saving-statistics=false
; autosave-interval=5
; autosave-slots=3
; In ticks
; minimum-latency-in-multiplayer=0
; In seconds
; multiplayer-initial-connection-timeout=10
; port=34197
; max-map-preview-chunk-side=64
; max-map-preview-threads=7
; In bytes
; max-multiplayer-script-reload-size=1048576
; Options: true, false
; enable-steam-networking=true
; proxy=
; proxy-username=
; proxy-password=
; Options: true, false
; check-updates=true
; Options: true, false
; enable-experimental-updates=false
; Options: true, false
; enable-new-mods=true
; Options: true, false
; use-mod-settings-per-save=true
; Options: true, false
; disable-minimal-mode=false
; Options: true, false
; disable-blueprint-storage=false
; Disables tracking which mod created/changed what prototype. Mainly for faster startup during development.
;
; Options: true, false
; disable-prototype-history=false
; Print a warning for all prototype values that were not accessed.
;
; Options: true, false
; check-unused-prototype-data=false
; Cache data stage prototype data for faster startup. Experimental.
;
; Options: true, false
; cache-prototype-data=false
; Options: true, false
; enable-razer-chroma-support=true
; Options: true, false
; enable-logitech-led-support=true
; Options: true, false
; enable-crash-log-uploading=true
; Options: true, false
; enable-heap-validation=true
; Options: true, false
; enable-threaded-message-pump=true
; Options: true, false
; enable-taskbar-animation=true
; Does nothing on Windows
;
; Options: true, false
; non-blocking-saving=false
; Related to MacOS
;
; Options: true, false
; discard-mouse-events-when-accessibility-zoomed=false
; Options: true, false
; enable-blueprint-storage-cloud-sync=false
; Options: true, false
; force-enable-factorio-version-check=false
; Options: true, false
; bring-window-to-top-on-click=true
; Options: fast, maximum
; multiplayer-compression-level=fast
; Options: none, fast, maximum
; autosave-compression-level=fast
; Socket to host RCON on when lauching MP server from the menu.
; local-rcon-socket=0.0.0.0:0
; Password for RCON when launching MP server from the menu.
; local-rcon-password=
[interface]
; Options: true, false
; automatic-ui-scale=true
; custom-ui-scale=1.000000
; tooltip-delay=0.040000
; entity-tooltip-delay=0.000000
; tooltip-offset=20
; output-console-delay=1200
; train-stop-label-angle=0.085526
; active-quick-bars=2
; shortcut-bar-rows=2
; Options: true, false
; autosort-inventory=true
; Options: true, false
; research-finished-stops-game=false
; Options: true, false
; use-item-groups=true
; Options: true, false
; use-item-subgroups=true
; Options: true, false
; use-version-filter-in-browse-games-gui=true
; Options: true, false
; use-version-filter-in-install-mods-gui=true
; Options: true, false
; play-sound-for-chat-messages=true
; Options: true, false
; fuzzy-search-enabled=false
; Options: true, false
; pick-ghost-cursor=false
; Options: true, false
; show-minimap=true
; Options: true, false
; show-tips-and-tricks=true
; Options: true, false
; show-tutorial-notifications=true
; Options: true, false
; show-turret-radius-when-blueprinting=false
; Options: true, false
; show-item-labels-in-cursor=true
; Options: true, false
; show-rail-block-visualization=true
; Options: true, false
; show-missing-logistic-network-icon=true
; Options: true, false
; show-interaction-indications=true
; Options: true, false
; show-grid-when-paused=true
; Options: true, false
; show-inserter-arrows-when-selected=true
; Options: true, false
; show-inserter-arrows-when-detailed-info-is-on=false
; Options: true, false
; show-pump-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-mining-drill-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-combinator-settings-when-detailed-info-is-on=false
; Options: true, false
; entity-tooltip-on-the-side=true
; Options: true, false
; show-mod-owners-in-tooltips=true
; Options: true, false
; show-descriptions-in-tooltips=true
; Options: true, false
; show-total-raw-in-recipe-tooltips=true
; debug-font-size=18
; train-visualization-length=5
[sound]
; master-volume=0.800000
; music-volume=0.500000
; game-effects-volume=0.700000
; gui-effects-volume=0.600000
; walking-sound-volume=0.250000
; environment-sounds-volume=0.550000
; alerts-volume=0.500000
; wind-volume=0.350000
; audible-distance=40.000000
; environment-audible-distance=30.000000
; maximum-environment-sounds=50
; active-gui-volume-modifier=0.800000
; active-gui-environment-volume-modifier=0.400000
; The maximum volume allowed for any sound.
; maximum-volume=2.000000
; ambient-music-pause-mean-seconds=45.000000
; ambient-music-pause-variance-seconds=30.000000
; Options: main-tracks-only, interleave-main-tracks-with-interludes, randomize-all
; ambient-music-mode=interleave-main-tracks-with-interludes
; zoom-audible-distance-coefficient=0.500000
; zoom-volume-coefficient=0.750000
[map-view]
; Options: true, false
; show-logistic-network=false
; Options: true, false
; show-electric-network=false
; Options: true, false
; show-turret-range=false
; Options: true, false
; show-pollution=true
; Options: true, false
; show-networkless-logistic-members=false
; Options: true, false
; show-train-station-names=true
; Options: true, false
; show-player-names=true
; Options: true, false
; show-non-standard-map-info=false
[debug]
; force=enemy
; Options: true, false
; capture-perf-statistics=false
; Options: always, debug, never
; show-fps=debug
; Options: always, debug, never
; show-detailed-info=debug
; Options: always, debug, never
; show-time-usage=debug
; Options: always, debug, never
; show-gpu-time-usage=debug
; Options: always, debug, never
; show-sprite-counts=never
; Options: always, debug, never
; show-lua-object-statistics=never
; Options: always, debug, never
; show-heat-buffer-info=never
; Options: always, debug, never
; show-multiplayer-waiting-icon=debug
; Options: always, debug, never
; show-multiplayer-statistics=debug
; Options: always, debug, never
; show-multiplayer-selection-rectangles=never
; Options: always, debug, never
; show-debug-info-in-tooltips=debug
; Options: always, debug, never
; hide-mod-guis=never
; Options: always, debug, never
; show-tile-grid=never
; Options: always, debug, never
; show-collision-rectangles=never
; Options: always, debug, never
; show-selection-rectangles=never
; Options: always, debug, never
; show-render-rectangles=never
; Options: always, debug, never
; show-entity-positions=never
; Options: always, debug, never
; show-entity-velocities=never
; Options: always, debug, never
; show-selected-entity-advanced-tiles=never
; Options: always, debug, never
; show-selected-input-transport-belts=never
; Options: always, debug, never
; show-paths=never
; Options: always, debug, never
; show-path-requests=never
; Options: always, debug, never
; show-next-waypoint-bb=never
; Options: always, debug, never
; show-target=never
; Options: always, debug, never
; show-unit-group-info=never
; Options: always, debug, never
; show-unit-behavior-info=never
; Options: always, debug, never
; show-pathfinder-fringe=never
; Options: always, debug, never
; show-path-cache=never
; Options: always, debug, never
; show-path-cache-paths=never
; Options: always, debug, never
; show-rail-paths=never
; Options: always, debug, never
; show-rolling-stock-count=never
; Options: always, debug, never
; show-rail-connections=never
; Options: always, debug, never
; show-rail-joints=never
; Options: always, debug, never
; show-rail-signal-states=never
; Options: always, debug, never
; show-rail-segment-collision-boxes=never
; Options: always, debug, never
; show-train-stop-point=never
; Options: always, debug, never
; show-train-braking-distance=never
; Options: always, debug, never
; show-train-signals=never
; Options: always, debug, never
; show-train-repathing=never
; Options: always, debug, never
; show-network-connected-entities=never
; Options: always, debug, never
; show-circuit-network-numbers=never
; Options: always, debug, never
; show-energy-sources-networks=never
; Options: always, debug, never
; show-active-state=never
; Options: always, debug, never
; show-wakeup-lists=never
; Options: always, debug, never
; show-transport-lines=never
; Options: always, debug, never
; show-transport-line-gaps=never
; Options: always, debug, never
; show-pollution-values=never
; Options: always, debug, never
; show-active-entities-on-chunk-counts=never
; Options: always, debug, never
; show-active-chunks=never
; Options: always, debug, never
; show-polluted-chunks=never
; Options: always, debug, never
; hide-chart-tags=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunks=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunk-values=never
; Options: always, debug, never
; show-bad-attack-chunks=never
; Options: always, debug, never
; show-tile-variations=never
; Options: always, debug, never
; show-raw-tile-transitions=never
; Options: always, debug, never
; show-fluid-box-fluid-info=never
; Options: always, debug, never
; show-environment-sound-info=never
; Options: always, debug, never
; show-environment-sound-area=never
; Options: always, debug, never
; show-selected-entity-audible-range=never
; Options: always, debug, never
; show-recently-played-sound-info=never
; Options: always, debug, never
; show-logistic-robot-targets=never
; Options: always, debug, never
; show-logistic-robots-on-map=never
; Options: always, debug, never
; show-recipe-icons-on-map=never
; Options: always, debug, never
; show-player-robots=never
; Options: always, debug, never
; show-fire-info=never
; Options: always, debug, never
; show-sticker-info=never
; Options: always, debug, never
; show-decorative-names=never
; Options: always, debug, never
; show-decorative-collision-rectangles=never
; Options: always, debug, never
; allow-increased-zoom=never
; Options: always, debug, never
; show-chunk-components=never
[multiplayer-lobby]
; name=
; description=
; Options: true, false
; visibility-public=true
; Options: true, false
; visibility-steam=true
; Options: true, false
; visibility-lan=true
; max-players=0
; Options: true, false
; ignore-player-limit-when-returning=false
; max-upload-in-kilobytes-per-second=0
; max-upload-slots=5
; password=
; tag-list=
; afk-auto-kick=0
; Options: true, false, admins-only
; allowed-commands=admins-only
; Options: true, false
; only-admins-can-pause=true
; Options: true, false
; autosave-only-on-server=true
; Options: true, false
; non-blocking-saving=true
; Options: true, false
; verify-user-identity=true
; Options: true, false
; enable-whitelist=false
[graphics]
; lights-render-quality=0.250000
; Default preferred display index should force finding primary monitor
; preferred-display-index=255
; screenshots-threads-count=8
; cache-sprite-atlas-count=1
; Options: true, false
; cache-sprite-atlas=false
; Options: true, false
; compress-sprite-atlas-cache=false
; Options: true, false
; texture-streaming=true
; streamed-atlas-physical-vram-size=0
; sprite-vertex-buffer-size=1048576
; max-texture-size=0
; max-threads=8
; 'low' and 'very-low' options are deprecated and will be migrated to 'normal'
;
; Options: high, normal, low, very-low
; graphics-quality=normal
; brightness=0
; contrast=0
; saturation=100
; Options: true, false
; full-screen=true
; Options: true, false
; minimize-on-focus-loss=false
; Options: true, false
; show-smoke=true
; Options: true, false
; show-clouds=true
; Options: true, false
; show-decoratives=true
; Options: true, false
; show-particles=true
; Options: true, false
; show-item-shadows=true
; Options: true, false
; show-inserter-shadows=true
; Options: true, false
; show-animated-water=true
; Options: true, false
; show-tree-distortion=true
; Options: true, false
; force-opengl=false
; Options: true, false
; v-sync=true
; Options: true, false
; high-quality-animations=true
; Options: true, false
; high-quality-shadows=false
; Options: true, false
; high-quality-terrain=true
; Minimum number of turrets required to turn on the turret range overdraw optimization
; turret-overdraw-minimum-count=4
; Scale at which the turret range overdraw optimization will start being applied
; turret-overdraw-scale-threshold=0.200000
; Options: true, false
; skip-vram-detection=false
; Options: true, false
; halt-rendering-when-minimized=true
; Options: true, false
; runtime-sprite-reload=false
; Options: true, false
; full-color-depth=true
; Options: true, false
; render-in-native-resolution=true
; Options: true, false
; use-flip-presentation-model=false
; Options: true, false
; debug-api=false
; Options: true, false
; discard-buffers-on-begin-frame=true
; Options: all, high, medium, low
; video-memory-usage=high
; Options: none, high-quality, low-quality
; texture-compression-level=high-quality
; Options: true, false
; compress-virtual-atlas=true
; Options: copy, copy-sequential, flip, flip-discard
; dxgi-presentation-model=copy
; Options: none, flush, wait-for-vblank, flush-and-wait-for-vblank
; dxgi-action-before-present=none
; relevant only for flip presentation models
;
; Options: true, false
; dxgi-allow-tearing=false
; Options: false, true, auto
; dxgi-flip-do-not-wait=false
; Options: true, false
; dxgi-present-restart=false
; dxgi-swap-chain-buffer-count=0
; dxgi-max-frame-latency=0
; dxgi-adapter-index=-1
; max-sprite-loading-threads=32
; Options: true, false
; gpu-accelerated-compression=true
; Options: true, false
; gpu-accelerated-mipmap-compression=true
; Options: true, false
; wait-until-mipmap-generation-finished=true
; Options: true, false
; check-for-unused-pixels=false
; ogl-depth-buffer-bit-depth=0
; Options: false, true, auto
; ogl-accelerated-renderer=auto
; Options: true, false
; ogl-double-buffered=true
; Set to true if mipmapped sprites render very blurry on your GPU. Limited support.
;
; Options: true, false
; legacy-gpu-no-mipmaps=false
; Options: true, false
; force-linear-magnification=false
; Options: true, false
; custom-mipmap-workaround=false
; Options: true, false
; buffer-rename-workaround=false
; Comma separated list of OpenGL extensions that should not be used (for example: ARB_copy_image,KHR_debug)
; disabled-opengl-extensions=

View File

@ -1,28 +0,0 @@
#!/bin/bash
set -eou pipefail
if [[ -f /run/secrets/username ]]; then
USERNAME=$(cat /run/secrets/username)
fi
if [[ -f /run/secrets/token ]]; then
TOKEN=$(cat /run/secrets/token)
fi
if [[ -z ${USERNAME:-} ]]; then
USERNAME="$(jq -j ".username" "$CONFIG/server-settings.json")"
fi
if [[ -z ${TOKEN:-} ]]; then
TOKEN="$(jq -j ".token" "$CONFIG/server-settings.json")"
fi
if [[ -z ${USERNAME:-} ]]; then
echo "You need to provide your Factorio username to update mods."
fi
if [[ -z ${TOKEN:-} ]]; then
echo "You need to provide your Factorio token to update mods."
fi
./update-mods.sh "$VERSION" "$MODS" "$USERNAME" "$TOKEN"

View File

@ -1,27 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--scenario2map "$SERVER_SCENARIO"

View File

@ -1,96 +0,0 @@
#!/bin/bash
set -eou pipefail
FACTORIO_VERSION=$1
MOD_DIR=$2
USERNAME=$3
TOKEN=$4
MOD_BASE_URL="https://mods.factorio.com"
print_step()
{
echo "$1"
}
print_success()
{
echo "$1"
}
print_failure()
{
echo "$1"
}
update_mod()
{
MOD_NAME="$1"
MOD_NAME_ENCODED="${1// /%20}"
print_step "Checking for update of mod $MOD_NAME..."
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED"
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
print_success " Custom mod not on $MOD_BASE_URL, skipped."
return 0
fi
MOD_INFO=$(echo "$MOD_INFO_JSON" | jq -j --arg version "$FACTORIO_VERSION" ".releases|reverse|map(select(.info_json.factorio_version as \$mod_version | \$version | startswith(\$mod_version)))[0]|.file_name, \";\", .download_url, \";\", .sha1")
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
if [[ $MOD_FILENAME == null ]]; then
print_failure " Not compatible with version"
return 0
fi
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Already up-to-date."
return 0
fi
print_step "Downloading..."
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
if [[ $HTTP_STATUS != 200 ]]; then
print_failure " Download failed: Code $HTTP_STATUS."
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
print_failure " Downloaded file missing!"
return 1
fi
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
print_failure " SHA1 mismatch!"
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
print_success " Download complete."
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Deleting old version: $file"
rm -f "$file"
fi
done
return 0
}
if [[ -f $MOD_DIR/mod-list.json ]]; then
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
if [[ $mod != base ]]; then
update_mod "$mod"
fi
done
fi

View File

@ -1,45 +0,0 @@
FROM frolvlad/alpine-glibc:alpine-3.12
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ENV PORT=34197 \
RCON_PORT=27015 \
VERSION=1.1.33 \
SHA1=525e0327698007ea6768e0de365c8e7b9ea652da \
SAVES=/factorio/saves \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID"
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN set -ox pipefail \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& apk add --update --no-cache --no-progress bash binutils curl file gettext jq libintl pwgen shadow su-exec \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" \
&& echo "$SHA1 $archive" | sha1sum -c \
|| (sha1sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
&& addgroup -g "$PGID" -S "$GROUP" \
&& adduser -u "$PUID" -G "$GROUP" -s /bin/sh -SDH "$USER" \
&& chown -R "$USER":"$GROUP" /opt/factorio /factorio
COPY files/*.sh /
COPY files/config.ini /opt/factorio/config/config.ini
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,16 +0,0 @@
version: '2'
services:
factorio:
build: .
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio
# environment:
# - PUID=1000
# - PGID=1000
# - UPDATE_MODS_ON_START=true
# - USERNAME=FactorioUsername
# - TOKEN=FactorioToken
# - PORT=34198

View File

@ -1,755 +0,0 @@
; version=8
; This is INI file : https://en.wikipedia.org/wiki/INI_file#Format
; Semicolons (;) at the beginning of the line indicate a comment. Comment lines are ignored.
[path]
read-data=__PATH__executable__/../../data
write-data=__PATH__executable__/../..
[general]
locale=
[other]
; Options: true, false
; verbose-logging=false
; Options: true, false
; log-saving-statistics=false
; autosave-interval=5
; autosave-slots=3
; In ticks
; minimum-latency-in-multiplayer=0
; In seconds
; multiplayer-initial-connection-timeout=10
; port=34197
; max-map-preview-chunk-side=64
; max-map-preview-threads=7
; In bytes
; max-multiplayer-script-reload-size=1048576
; Options: true, false
; enable-steam-networking=true
; proxy=
; proxy-username=
; proxy-password=
; Options: true, false
; check-updates=true
; Options: true, false
; enable-experimental-updates=false
; Options: true, false
; enable-new-mods=true
; Options: true, false
; use-mod-settings-per-save=true
; Options: true, false
; disable-minimal-mode=false
; Options: true, false
; disable-blueprint-storage=false
; Disables tracking which mod created/changed what prototype. Mainly for faster startup during development.
;
; Options: true, false
; disable-prototype-history=false
; Print a warning for all prototype values that were not accessed.
;
; Options: true, false
; check-unused-prototype-data=false
; Cache data stage prototype data for faster startup. Experimental.
;
; Options: true, false
; cache-prototype-data=false
; Options: true, false
; enable-razer-chroma-support=true
; Options: true, false
; enable-logitech-led-support=true
; Options: true, false
; enable-crash-log-uploading=true
; Options: true, false
; enable-heap-validation=true
; Options: true, false
; enable-threaded-message-pump=true
; Options: true, false
; enable-taskbar-animation=true
; Does nothing on Windows
;
; Options: true, false
; non-blocking-saving=false
; Related to MacOS
;
; Options: true, false
; discard-mouse-events-when-accessibility-zoomed=false
; Options: true, false
; enable-blueprint-storage-cloud-sync=false
; Options: true, false
; force-enable-factorio-version-check=false
; Options: true, false
; bring-window-to-top-on-click=true
; Options: fast, maximum
; multiplayer-compression-level=fast
; Options: none, fast, maximum
; autosave-compression-level=fast
; Socket to host RCON on when lauching MP server from the menu.
; local-rcon-socket=0.0.0.0:0
; Password for RCON when launching MP server from the menu.
; local-rcon-password=
[interface]
; Options: true, false
; automatic-ui-scale=true
; custom-ui-scale=1.000000
; tooltip-delay=0.040000
; entity-tooltip-delay=0.000000
; tooltip-offset=20
; output-console-delay=1200
; train-stop-label-angle=0.085526
; active-quick-bars=2
; shortcut-bar-rows=2
; Options: true, false
; autosort-inventory=true
; Options: true, false
; research-finished-stops-game=false
; Options: true, false
; use-item-groups=true
; Options: true, false
; use-item-subgroups=true
; Options: true, false
; use-version-filter-in-browse-games-gui=true
; Options: true, false
; use-version-filter-in-install-mods-gui=true
; Options: true, false
; play-sound-for-chat-messages=true
; Options: true, false
; fuzzy-search-enabled=false
; Options: true, false
; pick-ghost-cursor=false
; Options: true, false
; show-minimap=true
; Options: true, false
; show-tips-and-tricks=true
; Options: true, false
; show-tutorial-notifications=true
; Options: true, false
; show-turret-radius-when-blueprinting=false
; Options: true, false
; show-item-labels-in-cursor=true
; Options: true, false
; show-rail-block-visualization=true
; Options: true, false
; show-missing-logistic-network-icon=true
; Options: true, false
; show-interaction-indications=true
; Options: true, false
; show-grid-when-paused=true
; Options: true, false
; show-inserter-arrows-when-selected=true
; Options: true, false
; show-inserter-arrows-when-detailed-info-is-on=false
; Options: true, false
; show-pump-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-mining-drill-arrows-when-detailed-info-is-on=true
; Options: true, false
; show-combinator-settings-when-detailed-info-is-on=false
; Options: true, false
; entity-tooltip-on-the-side=true
; Options: true, false
; show-mod-owners-in-tooltips=true
; Options: true, false
; show-descriptions-in-tooltips=true
; Options: true, false
; show-total-raw-in-recipe-tooltips=true
; debug-font-size=18
; train-visualization-length=5
[sound]
; master-volume=0.800000
; music-volume=0.500000
; game-effects-volume=0.700000
; gui-effects-volume=0.600000
; walking-sound-volume=0.250000
; environment-sounds-volume=0.550000
; alerts-volume=0.500000
; wind-volume=0.350000
; audible-distance=40.000000
; environment-audible-distance=30.000000
; maximum-environment-sounds=50
; active-gui-volume-modifier=0.800000
; active-gui-environment-volume-modifier=0.400000
; The maximum volume allowed for any sound.
; maximum-volume=2.000000
; ambient-music-pause-mean-seconds=45.000000
; ambient-music-pause-variance-seconds=30.000000
; Options: main-tracks-only, interleave-main-tracks-with-interludes, randomize-all
; ambient-music-mode=interleave-main-tracks-with-interludes
; zoom-audible-distance-coefficient=0.500000
; zoom-volume-coefficient=0.750000
[map-view]
; Options: true, false
; show-logistic-network=false
; Options: true, false
; show-electric-network=false
; Options: true, false
; show-turret-range=false
; Options: true, false
; show-pollution=true
; Options: true, false
; show-networkless-logistic-members=false
; Options: true, false
; show-train-station-names=true
; Options: true, false
; show-player-names=true
; Options: true, false
; show-non-standard-map-info=false
[debug]
; force=enemy
; Options: true, false
; capture-perf-statistics=false
; Options: always, debug, never
; show-fps=debug
; Options: always, debug, never
; show-detailed-info=debug
; Options: always, debug, never
; show-time-usage=debug
; Options: always, debug, never
; show-gpu-time-usage=debug
; Options: always, debug, never
; show-sprite-counts=never
; Options: always, debug, never
; show-lua-object-statistics=never
; Options: always, debug, never
; show-heat-buffer-info=never
; Options: always, debug, never
; show-multiplayer-waiting-icon=debug
; Options: always, debug, never
; show-multiplayer-statistics=debug
; Options: always, debug, never
; show-multiplayer-selection-rectangles=never
; Options: always, debug, never
; show-debug-info-in-tooltips=debug
; Options: always, debug, never
; hide-mod-guis=never
; Options: always, debug, never
; show-tile-grid=never
; Options: always, debug, never
; show-collision-rectangles=never
; Options: always, debug, never
; show-selection-rectangles=never
; Options: always, debug, never
; show-render-rectangles=never
; Options: always, debug, never
; show-entity-positions=never
; Options: always, debug, never
; show-entity-velocities=never
; Options: always, debug, never
; show-selected-entity-advanced-tiles=never
; Options: always, debug, never
; show-selected-input-transport-belts=never
; Options: always, debug, never
; show-paths=never
; Options: always, debug, never
; show-path-requests=never
; Options: always, debug, never
; show-next-waypoint-bb=never
; Options: always, debug, never
; show-target=never
; Options: always, debug, never
; show-unit-group-info=never
; Options: always, debug, never
; show-unit-behavior-info=never
; Options: always, debug, never
; show-pathfinder-fringe=never
; Options: always, debug, never
; show-path-cache=never
; Options: always, debug, never
; show-path-cache-paths=never
; Options: always, debug, never
; show-rail-paths=never
; Options: always, debug, never
; show-rolling-stock-count=never
; Options: always, debug, never
; show-rail-connections=never
; Options: always, debug, never
; show-rail-joints=never
; Options: always, debug, never
; show-rail-signal-states=never
; Options: always, debug, never
; show-rail-segment-collision-boxes=never
; Options: always, debug, never
; show-train-stop-point=never
; Options: always, debug, never
; show-train-braking-distance=never
; Options: always, debug, never
; show-train-signals=never
; Options: always, debug, never
; show-train-repathing=never
; Options: always, debug, never
; show-network-connected-entities=never
; Options: always, debug, never
; show-circuit-network-numbers=never
; Options: always, debug, never
; show-energy-sources-networks=never
; Options: always, debug, never
; show-active-state=never
; Options: always, debug, never
; show-wakeup-lists=never
; Options: always, debug, never
; show-transport-lines=never
; Options: always, debug, never
; show-transport-line-gaps=never
; Options: always, debug, never
; show-pollution-values=never
; Options: always, debug, never
; show-active-entities-on-chunk-counts=never
; Options: always, debug, never
; show-active-chunks=never
; Options: always, debug, never
; show-polluted-chunks=never
; Options: always, debug, never
; hide-chart-tags=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunks=never
; Options: always, debug, never
; show-enemy-expansion-candidate-chunk-values=never
; Options: always, debug, never
; show-bad-attack-chunks=never
; Options: always, debug, never
; show-tile-variations=never
; Options: always, debug, never
; show-raw-tile-transitions=never
; Options: always, debug, never
; show-fluid-box-fluid-info=never
; Options: always, debug, never
; show-environment-sound-info=never
; Options: always, debug, never
; show-environment-sound-area=never
; Options: always, debug, never
; show-selected-entity-audible-range=never
; Options: always, debug, never
; show-recently-played-sound-info=never
; Options: always, debug, never
; show-logistic-robot-targets=never
; Options: always, debug, never
; show-logistic-robots-on-map=never
; Options: always, debug, never
; show-recipe-icons-on-map=never
; Options: always, debug, never
; show-player-robots=never
; Options: always, debug, never
; show-fire-info=never
; Options: always, debug, never
; show-sticker-info=never
; Options: always, debug, never
; show-decorative-names=never
; Options: always, debug, never
; show-decorative-collision-rectangles=never
; Options: always, debug, never
; allow-increased-zoom=never
; Options: always, debug, never
; show-chunk-components=never
[multiplayer-lobby]
; name=
; description=
; Options: true, false
; visibility-public=true
; Options: true, false
; visibility-steam=true
; Options: true, false
; visibility-lan=true
; max-players=0
; Options: true, false
; ignore-player-limit-when-returning=false
; max-upload-in-kilobytes-per-second=0
; max-upload-slots=5
; password=
; tag-list=
; afk-auto-kick=0
; Options: true, false, admins-only
; allowed-commands=admins-only
; Options: true, false
; only-admins-can-pause=true
; Options: true, false
; autosave-only-on-server=true
; Options: true, false
; non-blocking-saving=true
; Options: true, false
; verify-user-identity=true
; Options: true, false
; enable-whitelist=false
[graphics]
; lights-render-quality=0.250000
; Default preferred display index should force finding primary monitor
; preferred-display-index=255
; screenshots-threads-count=8
; cache-sprite-atlas-count=1
; Options: true, false
; cache-sprite-atlas=false
; Options: true, false
; compress-sprite-atlas-cache=false
; Options: true, false
; texture-streaming=true
; streamed-atlas-physical-vram-size=0
; sprite-vertex-buffer-size=1048576
; max-texture-size=0
; max-threads=8
; 'low' and 'very-low' options are deprecated and will be migrated to 'normal'
;
; Options: high, normal, low, very-low
; graphics-quality=normal
; brightness=0
; contrast=0
; saturation=100
; Options: true, false
; full-screen=true
; Options: true, false
; minimize-on-focus-loss=false
; Options: true, false
; show-smoke=true
; Options: true, false
; show-clouds=true
; Options: true, false
; show-decoratives=true
; Options: true, false
; show-particles=true
; Options: true, false
; show-item-shadows=true
; Options: true, false
; show-inserter-shadows=true
; Options: true, false
; show-animated-water=true
; Options: true, false
; show-tree-distortion=true
; Options: true, false
; force-opengl=false
; Options: true, false
; v-sync=true
; Options: true, false
; high-quality-animations=true
; Options: true, false
; high-quality-shadows=false
; Options: true, false
; high-quality-terrain=true
; Minimum number of turrets required to turn on the turret range overdraw optimization
; turret-overdraw-minimum-count=4
; Scale at which the turret range overdraw optimization will start being applied
; turret-overdraw-scale-threshold=0.200000
; Options: true, false
; skip-vram-detection=false
; Options: true, false
; halt-rendering-when-minimized=true
; Options: true, false
; runtime-sprite-reload=false
; Options: true, false
; full-color-depth=true
; Options: true, false
; render-in-native-resolution=true
; Options: true, false
; use-flip-presentation-model=false
; Options: true, false
; debug-api=false
; Options: true, false
; discard-buffers-on-begin-frame=true
; Options: all, high, medium, low
; video-memory-usage=high
; Options: none, high-quality, low-quality
; texture-compression-level=high-quality
; Options: true, false
; compress-virtual-atlas=true
; Options: copy, copy-sequential, flip, flip-discard
; dxgi-presentation-model=copy
; Options: none, flush, wait-for-vblank, flush-and-wait-for-vblank
; dxgi-action-before-present=none
; relevant only for flip presentation models
;
; Options: true, false
; dxgi-allow-tearing=false
; Options: false, true, auto
; dxgi-flip-do-not-wait=false
; Options: true, false
; dxgi-present-restart=false
; dxgi-swap-chain-buffer-count=0
; dxgi-max-frame-latency=0
; dxgi-adapter-index=-1
; max-sprite-loading-threads=32
; Options: true, false
; gpu-accelerated-compression=true
; Options: true, false
; gpu-accelerated-mipmap-compression=true
; Options: true, false
; wait-until-mipmap-generation-finished=true
; Options: true, false
; check-for-unused-pixels=false
; ogl-depth-buffer-bit-depth=0
; Options: false, true, auto
; ogl-accelerated-renderer=auto
; Options: true, false
; ogl-double-buffered=true
; Set to true if mipmapped sprites render very blurry on your GPU. Limited support.
;
; Options: true, false
; legacy-gpu-no-mipmaps=false
; Options: true, false
; force-linear-magnification=false
; Options: true, false
; custom-mipmap-workaround=false
; Options: true, false
; buffer-rename-workaround=false
; Comma separated list of OpenGL extensions that should not be used (for example: ARB_copy_image,KHR_debug)
; disabled-opengl-extensions=

View File

@ -1,98 +0,0 @@
#!/bin/bash
set -eoux pipefail
FACTORIO_VOL=/factorio
LOAD_LATEST_SAVE="${LOAD_LATEST_SAVE:-true}"
GENERATE_NEW_SAVE="${GENERATE_NEW_SAVE:-false}"
SAVE_NAME="${SAVE_NAME:-""}"
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
mkdir -p "$SCRIPTOUTPUT"
if [[ ! -f $CONFIG/rconpw ]]; then
# Generate a new RCON password if none exists
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
# Copy default settings if server-settings.json doesn't exist
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
NRTMPSAVES=$( find -L "$SAVES" -iname \*.tmp.zip -mindepth 1 | wc -l )
if [[ $NRTMPSAVES -gt 0 ]]; then
# Delete incomplete saves (such as after a forced exit)
rm -f "$SAVES"/*.tmp.zip
fi
if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
fi
if [[ $(id -u) = 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
fi
sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
NRSAVES=$(find -L "$SAVES" -iname \*.zip -mindepth 1 | wc -l)
if [[ $GENERATE_NEW_SAVE != true && $NRSAVES == 0 ]]; then
GENERATE_NEW_SAVE=true
SAVE_NAME=_autosave1
fi
if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -z "$SAVE_NAME" ]]; then
echo "If \$GENERATE_NEW_SAVE is true, you must specify \$SAVE_NAME"
exit 1
fi
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
fi
FLAGS=(\
--port "$PORT" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--rcon-port "$RCON_PORT" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json \
)
if [[ $LOAD_LATEST_SAVE == true ]]; then
FLAGS+=( --start-server-load-latest )
else
FLAGS+=( --start-server "$SAVE_NAME" )
fi
# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"

View File

@ -1,28 +0,0 @@
#!/bin/bash
set -eou pipefail
if [[ -f /run/secrets/username ]]; then
USERNAME=$(cat /run/secrets/username)
fi
if [[ -f /run/secrets/token ]]; then
TOKEN=$(cat /run/secrets/token)
fi
if [[ -z ${USERNAME:-} ]]; then
USERNAME="$(jq -j ".username" "$CONFIG/server-settings.json")"
fi
if [[ -z ${TOKEN:-} ]]; then
TOKEN="$(jq -j ".token" "$CONFIG/server-settings.json")"
fi
if [[ -z ${USERNAME:-} ]]; then
echo "You need to provide your Factorio username to update mods."
fi
if [[ -z ${TOKEN:-} ]]; then
echo "You need to provide your Factorio token to update mods."
fi
./update-mods.sh "$VERSION" "$MODS" "$USERNAME" "$TOKEN"

View File

@ -1,44 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
#chown -R factorio /factorio
if [[ ! -f $CONFIG/rconpw ]]; then
pwgen 15 1 >"$CONFIG/rconpw"
fi
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-scenario "$SERVER_SCENARIO" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json" \
--server-settings "$CONFIG/server-settings.json" \
--server-banlist "$CONFIG/server-banlist.json" \
--server-whitelist "$CONFIG/server-whitelist.json" \
--use-server-whitelist \
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-port "$RCON_PORT" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json

View File

@ -1,27 +0,0 @@
#!/bin/bash
set -eoux pipefail
if [[ -z ${1:-} ]]; then
echo "No argument supplied"
fi
SERVER_SCENARIO="$1"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
if [[ ! -f $CONFIG/server-settings.json ]]; then
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
if [[ ! -f $CONFIG/map-gen-settings.json ]]; then
cp /opt/factorio/data/map-gen-settings.example.json "$CONFIG/map-gen-settings.json"
fi
if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
exec /opt/factorio/bin/x64/factorio \
--scenario2map "$SERVER_SCENARIO"

View File

@ -1,96 +0,0 @@
#!/bin/bash
set -eou pipefail
FACTORIO_VERSION=$1
MOD_DIR=$2
USERNAME=$3
TOKEN=$4
MOD_BASE_URL="https://mods.factorio.com"
print_step()
{
echo "$1"
}
print_success()
{
echo "$1"
}
print_failure()
{
echo "$1"
}
update_mod()
{
MOD_NAME="$1"
MOD_NAME_ENCODED="${1// /%20}"
print_step "Checking for update of mod $MOD_NAME..."
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED"
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
print_success " Custom mod not on $MOD_BASE_URL, skipped."
return 0
fi
MOD_INFO=$(echo "$MOD_INFO_JSON" | jq -j --arg version "$FACTORIO_VERSION" ".releases|reverse|map(select(.info_json.factorio_version as \$mod_version | \$version | startswith(\$mod_version)))[0]|.file_name, \";\", .download_url, \";\", .sha1")
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
if [[ $MOD_FILENAME == null ]]; then
print_failure " Not compatible with version"
return 0
fi
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Already up-to-date."
return 0
fi
print_step "Downloading..."
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
if [[ $HTTP_STATUS != 200 ]]; then
print_failure " Download failed: Code $HTTP_STATUS."
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
print_failure " Downloaded file missing!"
return 1
fi
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
print_failure " SHA1 mismatch!"
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
print_success " Download complete."
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Deleting old version: $file"
rm -f "$file"
fi
done
return 0
}
if [[ -f $MOD_DIR/mod-list.json ]]; then
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
if [[ $mod != base ]]; then
update_mod "$mod"
fi
done
fi

114
CLAUDE.md Normal file
View File

@ -0,0 +1,114 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Docker image for running a Factorio headless server. It provides automated builds for multiple Factorio versions (stable and experimental) and supports both AMD64 and ARM64 architectures.
## Architecture
### Key Components
1. **Docker Image Build System**
- `build.py` - Python script that builds Docker images from `buildinfo.json`
- `docker/Dockerfile` - Main Dockerfile that creates the Factorio server image
- `buildinfo.json` - Contains version info, SHA256 checksums, and tags for all supported versions
- Supports multi-architecture builds (linux/amd64, linux/arm64) using Docker buildx
2. **Automated Updates**
- `update.sh` - Checks for new Factorio releases and updates `buildinfo.json`
- Updates README.md with new version tags
- Commits changes and tags releases automatically
- Run by GitHub Actions to keep images up-to-date
3. **Container Scripts**
- `docker/files/docker-entrypoint.sh` - Main entrypoint that configures and starts the server
- `docker/files/docker-update-mods.sh` - Updates mods on server start
- `docker/files/docker-dlc.sh` - Manages DLC (Space Age) activation
- `docker/files/scenario.sh` - Alternative entrypoint for launching scenarios
- `docker/files/players-online.sh` - Checks if players are online (for watchtower integration)
4. **RCON Client**
- `docker/rcon/` - C source for RCON client, built during Docker image creation
- Allows sending commands to the running server
## Common Development Commands
### Building Images
```bash
# Build a single architecture image locally
python3 build.py
# Build and push multi-architecture images
python3 build.py --multiarch --push-tags
```
### Running the Container
```bash
# Basic run command
docker run -d \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
factoriotools/factorio
# Using docker-compose
docker-compose up -d
```
### Linting
```bash
# Lint Dockerfiles
./lint.sh
```
### Testing Updates
```bash
# Check for new Factorio versions and update buildinfo.json
./update.sh
```
## Key Configuration
### Environment Variables
- `LOAD_LATEST_SAVE` - Load the most recent save (default: true)
- `GENERATE_NEW_SAVE` - Generate a new save if none exists (default: false)
- `SAVE_NAME` - Name of the save file to load/create
- `UPDATE_MODS_ON_START` - Update mods before starting (requires USERNAME/TOKEN)
- `DLC_SPACE_AGE` - Enable/disable Space Age DLC (default: true)
- `PORT` - UDP port for game server (default: 34197)
- `RCON_PORT` - TCP port for RCON (default: 27015)
### Volume Structure
All data is stored in a single volume mounted at `/factorio`:
```
/factorio/
├── config/ # Server configuration files
├── mods/ # Game modifications
├── saves/ # Save games
├── scenarios/ # Scenario files
└── script-output/ # Script output directory
```
## Version Management
The project maintains compatibility with multiple Factorio versions:
- Latest experimental version gets the `latest` tag
- Latest stable version gets the `stable` tag
- Each version also gets specific tags (e.g., `2.0.55`, `2.0`, `2`)
- Legacy versions back to 0.12 are supported
Version updates are automated via GitHub Actions that run `update.sh` periodically.
## Testing Changes
1. Modify `buildinfo.json` to test specific versions
2. Run `python3 build.py` to build locally
3. Test the container with your local data volume
4. For production changes, ensure `update.sh` handles version transitions correctly

136
README-ROOTLESS.md Normal file
View File

@ -0,0 +1,136 @@
# Rootless Docker Support
This document describes the rootless Docker images for Factorio, which are designed to work better with rootless Docker installations and avoid permission issues.
## What is Rootless Docker?
Rootless Docker allows running the Docker daemon and containers as a non-root user, which improves security by eliminating the need for root privileges. However, it introduces complexity with UID/GID mapping that can cause permission issues with volumes.
## Rootless Image Tags
For each regular Factorio image tag, there's a corresponding rootless tag with the `-rootless` suffix:
- `latest``latest-rootless`
- `stable``stable-rootless`
- `2.0.55``2.0.55-rootless`
- etc.
## Key Differences from Regular Images
1. **No dynamic UID/GID mapping**: The rootless images run as UID 1000 by default and don't support PUID/PGID environment variables
2. **No runtime chown operations**: Eliminates the recursive chown that can cause race conditions
3. **Simplified permissions**: All directories are created with open permissions (777) during build
4. **USER directive**: The container runs as non-root from the start
## Usage
### Basic Usage
```bash
docker run -d \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
factoriotools/factorio:stable-rootless
```
### With Rootless Docker
If you're running rootless Docker, the container will work out of the box:
```bash
# As your regular user (not root)
docker run -d \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v ~/factorio:/factorio \
--name factorio \
factoriotools/factorio:stable-rootless
```
### With Regular Docker
If you're running regular Docker but want to avoid permission issues:
```bash
# Pre-create the volume directory with your user's permissions
mkdir -p /opt/factorio
sudo chown -R $(id -u):$(id -g) /opt/factorio
# Run the container
docker run -d \
--user $(id -u):$(id -g) \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
factoriotools/factorio:stable-rootless
```
## Environment Variables
All the same environment variables from the regular image are supported, except:
- `PUID` - Not supported (container runs as UID 1000)
- `PGID` - Not supported (container runs as GID 1000)
## Migrating from Regular Images
If you're switching from a regular image to a rootless image:
1. Stop your existing container
2. Fix permissions on your volume (one time only):
```bash
sudo chown -R 1000:1000 /opt/factorio
# Or if you want to match your user:
sudo chown -R $(id -u):$(id -g) /opt/factorio
```
3. Start the new rootless container
## Troubleshooting
### Permission Denied Errors
If you get permission errors, ensure your volume directory is writable by UID 1000 or your user:
```bash
# Check current ownership
ls -la /opt/factorio
# Fix ownership for UID 1000 (default)
sudo chown -R 1000:1000 /opt/factorio
# Or fix for your current user
sudo chown -R $(id -u):$(id -g) /opt/factorio
```
### Running as a Different User
If you need to run as a different UID, override it at runtime:
```bash
docker run -d \
--user 2000:2000 \
-v /opt/factorio:/factorio \
factoriotools/factorio:stable-rootless
```
## Building Rootless Images
To build rootless images locally:
```bash
# Build for current architecture
python3 build-rootless.py
# Build and push multi-arch images
python3 build-rootless.py --multiarch --push-tags
```
## Why Use Rootless Images?
1. **Avoid permission issues**: No more files with unexpected ownership
2. **Better security**: Runs as non-root by default
3. **Simpler**: No complex permission logic at startup
4. **Faster startup**: No recursive chown operations
5. **Rootless Docker compatible**: Works seamlessly with rootless Docker installations

163
README.md
View File

@ -1,19 +1,19 @@
# Factorio [![Build Status](https://travis-ci.org/factoriotools/factorio-docker.svg?branch=master)](https://travis-ci.org/factoriotools/factorio-docker) ![Updater status](https://img.shields.io/endpoint?label=Updater%20status&logo=a&url=https%3A%2F%2Fhealthchecks.supersandro.de%2Fbadge%2F1a0a7698-445d-4e54-9e4b-f61a1544e01f%2FBO8VukOA%2Fmaintainer.shields) [![Docker Version](https://images.microbadger.com/badges/version/factoriotools/factorio.svg)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Pulls](https://img.shields.io/docker/pulls/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Stars](https://img.shields.io/docker/stars/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Microbadger Layers](https://images.microbadger.com/badges/image/factoriotools/factorio.svg)](https://microbadger.com/images/factoriotools/factorio "Get your own image badge on microbadger.com")
# Factorio [![Docker Version](https://img.shields.io/docker/v/factoriotools/factorio?sort=semver)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Pulls](https://img.shields.io/docker/pulls/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Stars](https://img.shields.io/docker/stars/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/)
> [!NOTE]
> Support for ARM is experimental. Expect crashes and lag if you try to run this on a raspberry pi.
[中文](./README_zh_CN.md)
* `1.1.33`, `1.1`, `latest`, `stable` [(1.1/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/1.1/Dockerfile)
* `1.0.0`, `1.0` [(1.0/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/1.0/Dockerfile)
* `0.18.47`, `0.18` [(0.18/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/0.18/Dockerfile)
* `0.17.79`, `0.17` [(0.17/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/0.17/Dockerfile)
* `0.16.51`, `0.16` [(0.16/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/0.16/Dockerfile)
* `0.15.40`, `0.15` [(0.15/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/0.15/Dockerfile)
* `0.14.23`, `0.14` [(0.14/Dockerfile)](https://github.com/factoriotools/factorio-docker/blob/master/0.14/Dockerfile)
<!-- start autogeneration tags -->
* `latest, 2.0.58`
* `2, 2.0, 2.0.55, stable, stable-2.0.55`
<!-- end autogeneration tags -->
## Tag descriptions
* `latest` - most up-to-date version (may be experimental).
* `stable` - version declared stable on [factorio.com](https://www.factorio.com).
* `stable` - version declared stable on [factorio.com](https://www.factorio.com) ([FFF-435 Since 2.0 versions gets released as experimental first, once stable it will be marked as stable](https://factorio.com/blog/post/fff-435)).
* `0.x` - latest version in a branch.
* `0.x.y` - a specific version.
* `0.x-z` - incremental fix for that version.
@ -42,7 +42,7 @@ sudo docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
@ -87,11 +87,20 @@ docker run -d -it \
docker attach factorio
```
### RCON (2.0.18+)
Alternativly (e.g. for scripting) the RCON connection can be used to send commands to the running factorio server.
This does not require the RCON connection to be exposed.
```shell
docker exec factorio rcon /h
```
### Upgrading
Before upgrading backup the save. It's easy to make a save in the client.
Ensure `-v` was used to run the server so the save is outside of the Docker container. The `docker rm` command completely destroys the container, which includes the save if it isn't stored in an data volume.
Ensure `-v` was used to run the server so the save is outside of the Docker container. The `docker rm` command completely destroys the container, which includes the save if it isn't stored in a data volume.
Delete the container and refresh the image:
@ -125,7 +134,7 @@ sudo docker run -d \
-e LOAD_LATEST_SAVE=false \
-e SAVE_NAME=replaceme \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
@ -140,7 +149,23 @@ sudo docker run -d \
-e GENERATE_NEW_SAVE=true \
-e SAVE_NAME=replaceme \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
To generate a new map with a specific preset (e.g., death-world):
```shell
sudo docker run -d \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
-e LOAD_LATEST_SAVE=false \
-e GENERATE_NEW_SAVE=true \
-e SAVE_NAME=replaceme \
-e PRESET=death-world \
--name factorio \
--restart=unless-stopped \
factoriotools/factorio
```
@ -160,7 +185,7 @@ docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
--entrypoint "/scenario.sh" \
factoriotools/factorio \
MyScenarioName
@ -176,7 +201,7 @@ docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
--entrypoint "/scenario2map.sh" \
factoriotools/factorio
MyScenarioName
@ -207,8 +232,8 @@ Create file `config/server-banlist.json` and add the banlisted users.
```json
[
"bad_person",
"other_bad_person"
"bad_person",
"other_bad_person"
]
```
@ -218,8 +243,8 @@ Create file `config/server-adminlist.json` and add the adminlisted users.
```json
[
"you",
"friend"
"you",
"friend"
]
```
@ -250,6 +275,42 @@ The `server-settings.json` file may then contain the variable references like th
"description": "${INSTANCE_DESC}",
```
### Environment Variables
These are the environment variables which can be specified at container run time.
| Variable Name | Description | Default | Available in |
|----------------------|----------------------------------------------------------------------|----------------|--------------|
| GENERATE_NEW_SAVE | Generate a new save if one does not exist before starting the server | false | 0.17+ |
| LOAD_LATEST_SAVE | Load latest when true. Otherwise load SAVE_NAME | true | 0.17+ |
| PORT | UDP port the server listens on | 34197 | 0.15+ |
| BIND | IP address (v4 or v6) the server listens on (IP\[:PORT]) | | 0.15+ |
| RCON_PORT | TCP port the rcon server listens on | 27015 | 0.15+ |
| SAVE_NAME | Name to use for the save file | _autosave1 | 0.17+ |
| PRESET | Map generation preset when GENERATE_NEW_SAVE is true | | 0.17+ |
| TOKEN | factorio.com token | | 0.17+ |
| UPDATE_MODS_ON_START | If mods should be updated before starting the server | | 0.17+ |
| USERNAME | factorio.com username | | 0.17+ |
| CONSOLE_LOG_LOCATION | Saves the console log to the specifies location | | |
| DLC_SPACE_AGE | Enables or disables the mods for DLC Space Age in mod-list.json[^1] | true | 2.0.8+ |
| MODS | Mod directory to use | /factorio/mods | 2.0.8+ |
**Note:** All environment variables are compared as strings
#### PRESET Values
The `PRESET` environment variable is used when generating a new map (when `GENERATE_NEW_SAVE=true`). It corresponds to Factorio's built-in map generation presets. Common values include:
- `default` - Normal settings
- `rich-resources` - Resources are more abundant
- `marathon` - Recipes and technologies are more expensive
- `death-world` - Biters are more aggressive and numerous
- `death-world-marathon` - Combines death-world and marathon settings
- `rail-world` - Resources are further apart, encouraging train usage
- `ribbon-world` - Map height is limited for a unique challenge
If PRESET is not specified or left empty, the map will be generated using the settings from `map-gen-settings.json` and `map-settings.json` without a preset.
## Container Details
The philosophy is to [keep it simple](http://wiki.c2.com/?KeepItSimple).
@ -284,16 +345,19 @@ The files in this volume should be owned by the factorio user, uid 845.
[Docker Compose](https://docs.docker.com/compose/install/) is an easy way to run Docker containers.
First get a [docker-compose.yml](https://github.com/factoriotools/factorio-docker/blob/master/0.17/docker-compose.yml) file. To get it from this repository:
* docker-engine >= 1.10.0 is required
* docker-compose >=1.6.0 is required
First get a [docker-compose.yml](https://github.com/factoriotools/factorio-docker/blob/master/docker/docker-compose.yml) file. To get it from this repository:
```shell
git clone https://github.com/factoriotools/factorio-docker.git
cd docker_factorio_server/0.17
cd factorio-docker/docker
```
Or make your own:
```shell
```yaml
version: '2'
services:
factorio:
@ -322,7 +386,7 @@ sudo docker-compose up -d
Ensure the `lan` setting in server-settings.json is `true`.
```shell
```json
"visibility":
{
"public": false,
@ -339,7 +403,7 @@ sudo docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
@ -360,6 +424,52 @@ For LAN games the VM needs an internal IP in order for clients to connect. One w
If you're looking for a simple way to deploy this to the Amazon Web Services Cloud, check out the [Factorio Server Deployment (CloudFormation) repository](https://github.com/m-chandler/factorio-spot-pricing). This repository contains a CloudFormation template that will get you up and running in AWS in a matter of minutes. Optionally it uses Spot Pricing so the server is very cheap, and you can easily turn it off when not in use.
## Using a reverse proxy
If you need to use a reverse proxy you can use the following nginx snippet:
```
stream {
server {
listen 34197 udp reuseport;
proxy_pass my.upstream.host:34197;
}
}
```
If your factorio host uses multiple IP addresses (very common with IPv6), you might additionally need to bind Factorio to a single IP (otherwise the UDP proxy might get confused with IP mismatches). To do that pass the `BIND` envvar to the container: `docker run --network=host -e BIND=2a02:1234::5678 ...`
## Rootless Docker Support
If you're experiencing permission issues or want better security, consider using the rootless images. These images are designed to work seamlessly with rootless Docker installations and avoid common permission problems.
### Rootless Image Tags
Each regular tag has a corresponding rootless version with the `-rootless` suffix:
- `latest-rootless`
- `stable-rootless`
- `2.0.55-rootless`
### Quick Start with Rootless
```shell
docker run -d \
-p 34197:34197/udp \
-p 27015:27015/tcp \
-v ~/factorio:/factorio \
--name factorio \
--restart=unless-stopped \
factoriotools/factorio:stable-rootless
```
Key differences:
- No `chown` command needed
- No PUID/PGID environment variables
- Runs as UID 1000 by default
- No permission issues with volumes
For more information, see the [Rootless Docker documentation](README-ROOTLESS.md).
## Troubleshooting
### My server is listed in the server browser, but nobody can connect
@ -386,3 +496,8 @@ Use the `PORT` environment variable to start the server on the a different port,
* [bplein](https://github.com/bplein/docker_factorio_server) - Coded scenario support
* [jaredledvina](https://github.com/jaredledvina/docker_factorio_server) - Contributed version updates
* [carlbennett](https://github.com/carlbennett) - Contributed version updates and bugfixes
[^1]: Space Age mods can also be individually enabled by using their name separated by space.
Example 1: Enable all by using `true`
Example 2: Enable all by listing the mod names `space-age elevated-rails quality`
Example 3: Enable only Elevated rails `elevated-rails`

View File

@ -1,41 +1,86 @@
# Factorio-异星工厂 [![Build Status](https://travis-ci.org/factoriotools/factorio-docker.svg?branch=master)](https://travis-ci.org/factoriotools/factorio-docker) ![Updater status](https://img.shields.io/endpoint?label=Updater%20status&logo=a&url=https%3A%2F%2Fhealthchecks.supersandro.de%2Fbadge%2F1a0a7698-445d-4e54-9e4b-f61a1544e01f%2FBO8VukOA%2Fmaintainer.shields) [![Docker Version](https://images.microbadger.com/badges/version/factoriotools/factorio.svg)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Pulls](https://img.shields.io/docker/pulls/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Stars](https://img.shields.io/docker/stars/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Microbadger Layers](https://images.microbadger.com/badges/image/factoriotools/factorio.svg)](https://microbadger.com/images/factoriotools/factorio "Get your own image badge on microbadger.com")
# Factorio [![Docker Version](https://img.shields.io/docker/v/factoriotools/factorio?sort=semver)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Pulls](https://img.shields.io/docker/pulls/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/) [![Docker Stars](https://img.shields.io/docker/stars/factoriotools/factorio.svg?maxAge=600)](https://hub.docker.com/r/factoriotools/factorio/)
版本信息可以在[这里](https://github.com/factoriotools/factorio-docker/blob/master/README.md#factorio------)找到
> [!注意]
> ARM 架构支持是实验性的。如果你尝试在 Raspberry Pi 上运行,可能会遇到崩溃和延迟问题。
[English](./README.md)
<!-- start autogeneration tags -->
* `2`, `2.0`, `2.0.55`, `latest`, `stable`, `stable-2.0.55`
* `2.0.54`
* `2.0.53`
* `2.0.52`
* `2.0.51`
* `2.0.50`
* `2.0.49`
* `2.0.48`
* `2.0`, `2.0.47`, `stable-2.0.47`
* `2.0.46`
* `2.0.45`
* `2.0.44`
* `2.0`, `2.0.43`, `stable-2.0.43`
* `2.0`, `2.0.42`, `stable-2.0.42`
* `2.0`, `2.0.41`, `stable-2.0.41`
* `2.0.40`
* `2.0`, `2.0.39`, `stable-2.0.39`
* `2.0.38`
* `2.0.37`
* `2.0.36`
* `2.0.35`
* `2.0.34`
* `2.0.33`
* `2.0`, `2.0.32`, `stable-2.0.32`
* `2.0.31`
* `2.0`, `2.0.30`, `stable-2.0.30`
* `2.0.29`
* `2.0`, `2.0.28`, `stable-2.0.28`
* `2.0.27`
* `2.0.26`
* `2.0.25`
* `2.0.24`
* `2.0`, `2.0.23`, `stable-2.0.23`
* `2.0.22`
* `2.0`, `2.0.21`, `stable-2.0.21`
* `2.0`, `2.0.20`, `stable-2.0.20`
* `2.0.19`
* `2.0.18`
* `2.0.17`
* `2.0.16`
* `2.0`, `2.0.15`, `stable-2.0.15`
* `2.0`, `2.0.14`, `stable-2.0.14`
* `2.0`, `2.0.13`, `stable-2.0.13`
* `1`, `1.1`, `1.1.110`, `stable-1.1.110`
* `1.0`, `1.0.0`
* `0.17`, `0.17.79`
* `0.16`, `0.16.51`
* `0.15`, `0.15.40`
* `0.14`, `0.14.23`
* `0.13`, `0.13.20`
* `0.12`, `0.12.35`<!-- end autogeneration tags -->
## 标签描述
* `latest` - 最新版本 (可能含有实验性功能).
* `stable` - 最新的稳定版本 [factorio.com](https://www.factorio.com).
* `0.x` - 某个分支上的最新版本
* `0.x.y` - 具体的版本
* `0.x-z` - 该版本的增量更新
* `latest` - 最新版本可能含有实验性功能)。
* `stable` - [factorio.com](https://www.factorio.com) 上声明为稳定的版本([FFF-435 自 2.0 版本起,版本首先作为实验版发布,一旦稳定就会被标记为稳定版](https://factorio.com/blog/post/fff-435))。
* `0.x` - 某个分支上的最新版本
* `0.x.y` - 具体的版本
* `0.x-z` - 该版本的增量修复。
## 什么是 Facotrio
## 什么是 Factorio
> 摘录自 [steam factorio 页面](https://store.steampowered.com/app/427520/Factorio/)
[Factorio](https://www.factorio.com) 是一款建造和维护工厂的游戏。
「异星工厂」Factorio 是一款建造工业生产流水线并保持其高效运转的游戏
在游戏中,你将挖掘资源、研发科技、建设基础设施、自动化生产并与敌人战斗。发挥你的想象力来设计工厂,将简单的元素组合成巧妙的结构,运用管理技能保持其正常运转,最后保护它不受那些不太喜欢你的生物的侵害
游戏中,你可以抠矿、搞科研、盖工厂、建设自动生产流水线,同时还要与异星虫子们互相伤害
游戏非常稳定,并为建造大规模工厂进行了优化。你可以创建自己的地图,用 Lua 编写模组,或通过多人游戏与朋友一起游戏
你将从一无所有艰辛起步。挥斧砍树,抡镐抠矿,手搓机械臂和传送带,然而像这样一直搞下去并没有什么卵用。因此,你需要高效的大规模发电厂,庞大的石油化工体系,壮观的全自动化产业链,以及替你东奔西走的机器人大队,让你成为物资储备丰盈工业帝国的真正操控者!
然而,总有一群刁民想害你。这个星球上的土著虫群对你在自家后院里瞎折腾的行为很不爽,总有一天这群刁民会联合起来找你麻烦。因此,你要制造武器、建立防御、准备镇压,让它们知道谁才是真正的主宰者。
你可以在多人游戏中加入不同的阵营,在大触们的带领下与朋友们分工协作, 一起建设恢弘无比的工业园区。
Factorio的模组支持吸引了全世界的设计师参与到对游戏的完善和革新中来从优化调整到游戏辅助甚至对游戏的彻底翻新日新月异的模组将为你不断提供新的乐趣。
除了游戏核心的自由模式和沙盒模式之外任务包还提供了更多不同形式的游戏挑战这已经作为一个免费的DLC提供给玩家了。
对随机生成的地图不满意?不满足于原生游戏任务?这都不是事儿。通过内置的地图编辑器,你可以任意修改地图,配置地形、建筑、敌人等各种元素。如果你是大触,还可以添加自定义脚本,让你的游戏更具独创性、更加阴吹思婷!
**注意**:这个仓库仅包含游戏服务端. 游戏本体可以在 [factorio.com](factorio.com)、 [Steam](https://store.steampowered.com/app/427520/Factorio/)、[GOG.com](https://www.gog.com/game/factorio) 和 [Humble Bundle](https://www.humblebundle.com/store/factorio) 上找到。
**注意**:这仅仅是服务端。完整游戏可在 [Factorio.com](https://www.factorio.com)、[Steam](https://store.steampowered.com/app/427520/)、[GOG.com](https://www.gog.com/game/factorio) 和 [Humble Bundle](https://www.humblebundle.com/store/factorio) 获得。
## 使用方法
### 快速入门
### 快速开始
运行服务端以在指定目录下生成必要的配置文件以及存档,`/opt/factorio` 也许是一个不错的选择
运行服务端以创建必要的文件夹结构和配置文件。在这个例子中,数据存储在 `/opt/factorio`
```shell
sudo mkdir -p /opt/factorio
@ -45,59 +90,67 @@ sudo docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
这样一来, 服务端会使用 `/opt/factorio/saves` 中最新的存档进行游戏。
对于 Docker 新手,这里解释一下选项:
你一定想知道上面那些咒语是什么意思:
* `-d` - 以守护进程方式运行("分离"模式)。
* `-p` - 暴露端口。
* `-v` - 将本地文件系统的 `/opt/factorio` 挂载到容器中的 `/factorio`
* `--restart` - 如果服务端崩溃或系统启动时重启服务端。
* `--name` - 将容器命名为 "factorio"(否则它会有一个有趣的随机名称)。
* `-d` - 以守护进程方式运行 ("detached")
* `-p` - 暴露宿主机 (host) 某些端口。
* `-v` - 将宿主机中 `/opt/factorio` 目录挂载到docker容器的 `/factorio` 目录。
* `--restart` - 在宿主重启或服务端运行崩溃后重启服务端。
* `--name` - 将docker容器命名为 "factorio" (否则docker会给他随机起一个搞怪名字)。
需要 `chown` 命令是因为在 0.16+ 版本中,出于安全原因,我们不再以 root 身份运行游戏服务端,而是以用户 ID 为 845 的 'factorio' 用户身份运行。因此主机必须允许该用户写入这些文件
`chown` 命令用来更改服务端所在目录的所有权用户以及用户组为了安全起见我们并不希望游戏直接在root用户权限下运行因此将用户id更改为845从而服务端允许该用户在目录中进行读、写、运行操作。
查看日志以搞清楚发生了什么。
检查日志以查看发生了什么:
```shell
docker logs factorio
```
停止docker容器 (服务端)。
停止服务端
```shell
docker stop factorio
```
运行过服务端之后可以`/opt/factorio/config` 目录中找到 `server-settings.json` 文件,修改改文件以定制你自己的服务端
在在 `/opt/factorio/config` 文件夹中有一个 `server-settings.json` 文件。根据你的喜好修改它并重启服务端
```shell
docker start factorio
```
现在试试连接服务端。如果没有正常运行的话请按照上面步骤查看日志。
试连接服务端。如果无法正常工作,请检查日志。
### Console-终端
### 控制台
为了运行在服务端终端中运行命令,需要通过 `-it` 参数在交互模式启动服务端。通过 `docker attach` 连接终端从而可以输入命令。
要向服务端发出控制台命令,请使用 `-it` 交互模式启动服务端。使用 `docker attach` 打开控制台,然后输入命令。
```shell
docker run -d -it \
--name factorio \
factoriotools/factorio
docker attach factorio
```
### 升级服务端
### RCON (2.0.18+)
在升级服务端之前请务必**备份存档**,在客户端(也就是你的游戏中)备份存档相当容易(保存就好)
或者(例如用于脚本),可以使用 RCON 连接向正在运行的 factorio 服务端发送命令
这不需要暴露 RCON 连接。
请确保在启动服务端时使用了 `-v` 参数,从而服务端将会把存档写在你指定的挂在目录中。`docker rm` 命令会彻底删除运行 facotrio 服务端的容器,也同时会删除容器的整个文件系统实例,因此如果没有挂载外部目录的话,存档也会被删除哦。
```shell
docker exec factorio rcon /h
```
### 更新
在升级服务端之前,请备份存档。在客户端中制作存档很容易。
确保在运行服务端时使用了 `-v` 参数,这样存档就在 Docker 容器外部。`docker rm` 命令会完全销毁容器,如果存档没有存储在数据卷中,也会包括存档。
删除容器并刷新镜像:
```shell
docker stop factorio
@ -105,21 +158,21 @@ docker rm factorio
docker pull factoriotools/factorio
```
然后就像前面说的那样启动服务端,大概一分钟后新的服务端就已经在运行中啦,并且存档和设置还和原来一样
现在像之前一样运行服务端。大约一分钟后,新版本的 Factorio 应该就会运行起来,完整保留存档和配置
### 存档
在第一次运行服务端的时候,服务端会根据 `/opt/factorio/config` 目录中的 `map-gen-settings.json``map-settings.json` 配置文件的内容,在 `/opt/factorio/saves` 目录下会生成一张新地图(存档)`_autosave1.zip`。之后如果在停掉之后再次运行,服务端会载入最新的存档。
服务端首次启动时会生成一个名为 `_autosave1.zip` 的新地图。使用 `/opt/factorio/config` 中的 `map-gen-settings.json``map-settings.json` 文件作为地图设置。在后续运行中使用最新的存档。
如果想要运行一个旧存档,你需要停止运行中的服务端,并且运行一个命令 `touch oldsave.zip` 这会重置日期然后重新启动服务端。或者你可以通过删除所有其他存档只留下想要运行的存档来完成同样的目的
要加载旧存档,请停止服务端并运行命令 `touch oldsave.zip`。这会重置日期然后重服务端。另一个选择是删除除一个存档外的所有存档
如果想生成一个新的存档,你需要停止运行中的服务端,然后删除所有存档再启动服务端就好
要生成新地图,请停止服务端,删除所有存档并重启服务端。
#### 在运行命令中直接指定存档(需要 0.17.79-2+ 版本
#### 直接指定存档0.17.79-2+
你可以在启动服务端时通过设置一个特殊的环境变量来载入一个特定存档:
你可以通过一组环境变量配置服务端来指定要加载的特定存档:
设置 `SAVE_NAME` `saves` 中你想运行的存档名,去掉 `.zip` 后缀
要加载现有存档,请将 `SAVE_NAME` 设置为位于 `saves` 目录中的现有存档文件名,不包含 `.zip` 扩展名
```shell
sudo docker run -d \
@ -129,11 +182,11 @@ sudo docker run -d \
-e LOAD_LATEST_SAVE=false \
-e SAVE_NAME=replaceme \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
要生成一个新存档,设置 `GENERATE_NEW_SAVE=true`,同时指定存档名 `SAVE_NAME`
要生成新地图,请设置 `GENERATE_NEW_SAVE=true` 并指定 `SAVE_NAME`
```shell
sudo docker run -d \
@ -144,20 +197,19 @@ sudo docker run -d \
-e GENERATE_NEW_SAVE=true \
-e SAVE_NAME=replaceme \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
### Mods-模组
将模组拷贝至 `mods` 目录下,然后重启服务端即可
将模组复制到 mods 文件夹中并重启服务端。
对于 `0.17` 及以上版本,新增 `UPDATE_MODES_ON_START` 环境变量,如果将其设置为 `true`,在服务端启动时将会更新所有的模组。请注意,应用此设置时,必须通过 docker secrets、环境变量或者在 `server-settings.json` 中填写相应字段来提供一个合法的 [Facotrio 用户名以及 Token](https://www.factorio.com/profile),否则服务端不会启动。
从 0.17 版本开始,添加了一个新的环境变量 `UPDATE_MODS_ON_START`,如果设置为 `true`在服务端启动时更新模组。如果设置了此选项,必须提供有效的 [Factorio 用户名和令牌](https://www.factorio.com/profile),否则服务端不会启动。它们可以设置为 docker secrets、环境变量或从 server-settings.json 文件中获取。
### Scenarios-场景
如果你希望新启动一个场景(而不是从某一个存档中启动),你需要通过另一个备选 `entrypoint` 来启动我们的 factorio-docker 镜像:通过运行以下命令,使用 `/factorio/entrypoints` 目录中的示例 entrypoint 文件来启动服务端。仔细观察后就能发现这只是在之前的命令基础上增加了 `--entrypoint` 设置并在最后新增了一个参数用来指示 `scenarios` 目录中想要启动的场景的文件名
如果你想从全新开始启动场景(而不是从保存的地图),你需要从备用入口点启动 docker 镜像。为此,请使用存储在卷中 /factorio/entrypoints 目录中的示例入口点文件,并使用以下语法启动镜像。请注意,这是正常语法,添加了 --entrypoint 设置和末尾的附加参数,这是 Scenarios 文件夹中场景的名称
```shell
docker run -d \
@ -165,7 +217,7 @@ docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
--entrypoint "/scenario.sh" \
factoriotools/factorio \
MyScenarioName
@ -173,7 +225,7 @@ docker run -d \
### 将场景转换为常规地图
如果你想把你的场景导出为一个常规的地图存档,类似启动一个新的场景,我们可以通过一个备选 `entrypoint` 文件来达到这个效果:服务端在运行后会将场景转换成一个常规地图存档放置在你的 `saves` 目录中,然后你就可以像平常那样启动服务端了
如果你想场景导出为保存的地图可以使用类似于上述场景用法的示例入口点。Factorio 将运行一次,将场景转换为 saves 目录中的保存地图。然后使用标准选项重启 docker 镜像将加载该地图,就像上述场景示例刚启动的场景一样
```shell
docker run -d \
@ -181,7 +233,7 @@ docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
--entrypoint "/scenario2map.sh" \
factoriotools/factorio
MyScenarioName
@ -189,51 +241,51 @@ docker run -d \
### RCON
config/rconpw 文件中设置RCON密码。 如果 rconpw 文件不存在,将会自动生成含有随机密码的该文件
`rconpw` 文件中设置 RCON 密码。如果 `rconpw` 不存在,将生成随机密码
如果想要更改密码,请停止服务端,编辑rconpw文件并重启服务端。
要更改密码,请停止服务端,修改 `rconpw`,然后重启服务端。
如果想要禁用RCON请不要在启动命令中加入 -p 27015:27015/tcp 参数在宿主机服务器中停止暴露rcon端口这时RCON将继续在docker容器中运行但不可达
要"禁用" RCON请不要暴露端口 27015即不使用 `-p 27015:27015/tcp` 启动服务端。RCON 仍在运行,但没有人可以连接到它
### 白名单 (0.15.3+)
创建文件 `config/server-whitelist.json` 然后将用户名加入到该json中
创建文件 `config/server-whitelist.json` 并添加白名单用户
```json
[
"you",
"friend"
"you",
"friend"
]
```
### 黑名单 (0.17.1+)
创建文件 `config/server-banlist.json` 然后将用户名加入到该json中
创建文件 `config/server-banlist.json` 并添加黑名单用户
```json
[
"bad_person",
"other_bad_person"
"bad_person",
"other_bad_person"
]
```
### 管理员列表 (0.17.1+)
创建文件 `config/server-adminlist.json` 然后将用户名加入到该json中
创建文件 `config/server-adminlist.json` 并添加管理员用户
```json
[
"you",
"friend"
"you",
"friend"
]
```
### 自定义配置文件 (0.17.x+)
原始的 factorio 服务端并不支持配置文件中添加环境变量,这里提供一个变通办法:通过在 docker-compose 中使用 `envsubst` 命令,在服务端启动时根据环境变量动态生成配置文件:
开箱即用的 factorio 不支持配置文件中环境变量。一个解决方法是使用 `envsubst`,它在启动期间从 docker-compose 中设置的环境变量动态生成配置文件:
下面的例子将用相应的环境变量来填充 `server-settings.json` 中的字段。
替换 server-settings.json 的示例:
```yaml
factorio_1:
@ -249,26 +301,47 @@ factorio_1:
entrypoint: /bin/sh -c "mkdir -p /factorio/config && envsubst < /server-settings.json > /factorio/config/server-settings.json && exec /docker-entrypoint.sh"
```
`server-settings.json` 中可能提供一些供环境变量来替换的字段
然后 `server-settings.json` 文件可能包含这样的变量引用
```json
"name": "${INSTANCE_NAME}",
"description": "${INSTANCE_DESC}",
```
### 容器相关的细节
### 环境变量
[保持简单](http://wiki.c2.com/?KeepItSimple)的哲学
这些是可以在容器运行时指定的环境变量
+ 服务端应当可以自启动
+ 在环境变量和配置文件中倾向于配置文件
+ 只使用一个数据卷(挂载目录)
| 变量名 | 描述 | 默认值 | 可用版本 |
|---------------------|----------------------------------------------------------------|----------------|--------------|
| GENERATE_NEW_SAVE | 如果在启动服务端之前不存在存档,则生成新存档 | false | 0.17+ |
| LOAD_LATEST_SAVE | 为 true 时加载最新存档。否则加载 SAVE_NAME | true | 0.17+ |
| PORT | 服务端监听的 UDP 端口 | 34197 | 0.15+ |
| BIND | 服务端监听的 IP 地址v4 或 v6(IP\[:PORT]) | | 0.15+ |
| RCON_PORT | rcon 服务端监听的 TCP 端口 | 27015 | 0.15+ |
| SAVE_NAME | 存档文件使用的名称 | _autosave1 | 0.17+ |
| TOKEN | factorio.com 令牌 | | 0.17+ |
| UPDATE_MODS_ON_START| 是否在启动服务端之前更新模组 | | 0.17+ |
| USERNAME | factorio.com 用户名 | | 0.17+ |
| CONSOLE_LOG_LOCATION| 将控制台日志保存到指定位置 | | |
| DLC_SPACE_AGE | 在 mod-list.json 中启用或禁用 DLC Space Age 的模组[^1] | true | 2.0.8+ |
| MODS | 要使用的模组目录 | /factorio/mods | 2.0.8+ |
**注意**:所有环境变量都作为字符串进行比较
## 容器细节
理念是[保持简单](http://wiki.c2.com/?KeepItSimple)。
* 服务端应该自启动。
* 优先使用配置文件而不是环境变量。
* 使用一个数据卷。
### 数据卷
为了保持简单,我们的 docker 服务端只使用一个数据卷挂载到容器中的 `/factorio` 目录。其中包含了所有的配置模组和存档。
为了保持简单,容器使用挂载在 `/factorio` 的单个卷。此卷存储配置模组和存档。
在这个数据卷中所有的文件应当被 uid 为 845 的 factorio 专有用户拥有(为了安全)
此卷中的文件应该由 factorio 用户拥有uid 845。
```text
factorio
@ -286,20 +359,23 @@ factorio_1:
`-- _autosave1.zip
```
### Docker Compose
## Docker Compose
[Docker Compose](https://docs.docker.com/compose/install/) 提供了一种便捷的容器运行方式
[Docker Compose](https://docs.docker.com/compose/install/) 是运行 Docker 容器的简便方法
首先获取一个 [docker-compose.yml](https://github.com/factoriotools/factorio-docker/blob/master/0.17/docker-compose.yml) 文件。假设你准备使用我们提供的:
* 需要 docker-engine >= 1.10.0
* 需要 docker-compose >=1.6.0
首先获取一个 [docker-compose.yml](https://github.com/factoriotools/factorio-docker/blob/master/docker/docker-compose.yml) 文件。从此仓库获取:
```shell
git clone https://github.com/factoriotools/factorio-docker.git
cd docker_factorio_server/0.17
cd factorio-docker/docker
```
或者假设你想自己编写一个
或者创建你自己的
```shell
```yaml
version: '2'
services:
factorio:
@ -311,7 +387,7 @@ services:
- /opt/factorio:/factorio
```
现在通过 cd 命令进入到 `docker-compose.yml` 所在的目录然后运行下面的命令
现在 cd 到包含 docker-compose.yml 的目录并运行
```shell
sudo mkdir -p /opt/factorio
@ -321,14 +397,14 @@ sudo docker-compose up -d
### 端口
- `34197/udp` - 游戏服务端(必)。可以通过改变 `PORT` 环境变量来改变
- `27015/tcp` - RCON可选
* `34197/udp` - 游戏服务端(必)。可以通过 `PORT` 环境变量更改
* `27015/tcp` - RCON可选
## 局域网游戏
确保 `server-settings.json` 中的 `lan` 字段被设置为 `true`
确保 server-settings.json 中的 `lan` 设置为 `true`
```shell
```json
"visibility":
{
"public": false,
@ -336,7 +412,7 @@ sudo docker-compose up -d
},
```
在启动服务端时假如 `--network=host` 参数,从而客户端可以自动找到局域网游戏参考 快速入门 章节
使用 `--network=host` 选项启动容器,以便客户端可以自动找到局域网游戏参考快速入门来创建 `/opt/factorio` 目录
```shell
sudo docker run -d \
@ -345,51 +421,70 @@ sudo docker run -d \
-p 27015:27015/tcp \
-v /opt/factorio:/factorio \
--name factorio \
--restart=always \
--restart=unless-stopped \
factoriotools/factorio
```
## 其他平台上部署
## 部署到其他平台
### Vagrant
[Vagrant](https://www.vagrantup.com/) 是一种通过虚拟机来运行 Docker 的便捷方式。 在 [Factorio Vagrant box repository](https://github.com/dtandersen/factorio-lan-vagrant) 中有一个示例 Vagrantfile。
[Vagrant](https://www.vagrantup.com/) 是设置虚拟机VM运行 Docker 的简便方法。[Factorio Vagrant box 仓库](https://github.com/dtandersen/factorio-lan-vagrant)包含一个示例 Vagrantfile。
对于局域网游戏Vagrant 虚拟机需要一个内部 IP 从而使游戏可达。一种方式是通过在一个空开网络中部署。虚拟机使用 DHCP 方式来获取一个 IP 地址。同时必须转发 34197 端口
对于局域网游戏VM 需要内部 IP 以便客户端连接。一种方法是使用公共网络。VM 使用 DHCP 获取 IP 地址。VM 还必须转发端口 34197。
```ruby
config.vm.network "public_network"
config.vm.network "forwarded_port", guest: 34197, host: 34197
```
### AWS 部署
### Amazon Web Services (AWS) 部署
如果你想找一个傻瓜教程,请看这个[仓库](https://github.com/m-chandler/factorio-spot-pricing)。这个仓库包含一个可以让你在几分钟内在 AWS 上搭建服务端的 CloudFormation 模板。同时它支持 Spot Pricing 因此费用会非常便宜,而且你可以在不用的时候把服务器关掉
如果你正在寻找一种简单的方法将此部署到 Amazon Web Services 云,请查看 [Factorio Server Deployment (CloudFormation) 仓库](https://github.com/m-chandler/factorio-spot-pricing)。仓库包含一个 CloudFormation 模板,可以让你在几分钟内在 AWS 上运行起来。它可选择使用 Spot Pricing因此服务端非常便宜,你可以在不使用时轻松关闭它
## 疑难杂症
## 使用反向代理
### 我可以在服务器列表中看到我的服务器但就是无法连接
如果你需要使用反向代理,可以使用以下 nginx 片段:
查看 log如果有一行说 `Own address is RIGHT IP:WRONG PORT`,那么这个问题就有可能是 Docker Proxy 导致的。 如果 IP 和端口都是正确的,那么有可能是端口转发或者防火墙出了问题。
```
stream {
server {
listen 34197 udp reuseport;
proxy_pass my.upstream.host:34197;
}
}
```
在默认情况下Docker 通过一个代理来转发网络请求。这个代理会改变 UDP 端口,因此会监测到上面的端口错误。更多细节请移步 *[Incorrect port detected for docker hosted server](https://forums.factorio.com/viewtopic.php?f=49&t=35255)*
如果你的 factorio 主机使用多个 IP 地址IPv6 非常常见),你可能还需要将 Factorio 绑定到单个 IP否则 UDP 代理可能会因 IP 不匹配而混乱)。要做到这一点,将 `BIND` 环境变量传递给容器:`docker run --network=host -e BIND=2a02:1234::5678 ...`
为了修复错误端口问题,在启动 Docker 服务时加上 `--userland-proxy=false`。这样一来 Docker 就会通过 iptables 来转发请求从而不走代理。可以通过设置 `DOCKER_OPTS` 环境变量或者改变 Docker systemd service 中的 `ExecStart` 字段来添加这一参数。不同的操作系统可能有不同的配置方式。
## 疑难解答
### 我不用 34197 端口就没人可以连我的服务器
### 我的服务端在服务端浏览器中列出,但没有人可以连接
如果一定要改端口,请使用 `PORT` 环境变量更改。例如 `docker run -e PORT=34198`。这样会更改端口监测中的目标端口。通过 `-p 34198:34197` 方式更改端口对于私人服务器来说是可行的,但这样一来服务器浏览器就没有办法检测到正确的端口了
检查日志。如果有一行显示 `Own address is RIGHT IP:WRONG PORT`,那么这可能是由 Docker 代理引起的。如果 IP 和端口是正确的,可能是端口转发或防火墙问题
默认情况下Docker 通过代理路由流量。代理更改源 UDP 端口,因此检测到错误的端口。有关详细信息,请参阅论坛帖子 *[docker 托管服务端检测到错误端口](https://forums.factorio.com/viewtopic.php?f=49&t=35255)*
为了修复错误端口,使用 `--userland-proxy=false` 开关启动 Docker 服务。Docker 将使用 iptables 规则而不是代理路由流量。将开关添加到 `DOCKER_OPTS` 环境变量或 Docker systemd 服务定义中的 `ExecStart`。具体情况因操作系统而异。
### 当我在 34197 之外的端口上运行服务端时,没有人可以从服务端浏览器连接
使用 `PORT` 环境变量在不同端口上启动服务端,例如 `docker run -e "PORT=34198"`。这会更改用于端口检测的数据包的源端口。`-p 34198:34197` 对于私人服务端工作正常,但服务端浏览器检测到错误的端口。
## 贡献者
* [dtandersen](https://github.com/dtandersen) - Maintainer
* [Fank](https://github.com/Fankserver) - Programmer of the Factorio watchdog that keeps the version up-to-date.
* [SuperSandro2000](https://github.com/supersandro2000) - CI Guy, Maintainer and runner of the Factorio watchdog. Contributed version updates and wrote the Travis scripts.
* [DBendit](https://github.com/DBendit/docker_factorio_server) - Coded admin list, ban list support and contributed version updates
* [Zopanix](https://github.com/zopanix/docker_factorio_server) - Original Author
* [Rfvgyhn](https://github.com/Rfvgyhn/docker-factorio) - Coded randomly generated RCON password
* [gnomus](https://github.com/gnomus/docker_factorio_server) - Coded wite listing support
* [bplein](https://github.com/bplein/docker_factorio_server) - Coded scenario support
* [jaredledvina](https://github.com/jaredledvina/docker_factorio_server) - Contributed version updates
* [carlbennett](https://github.com/carlbennett) - Contributed version updates and bugfixes
* [Thrimbda](https://github.com/Thrimbda) - 中文翻译
* [dtandersen](https://github.com/dtandersen) - 维护者
* [Fank](https://github.com/Fankserver) - Factorio 监视程序的程序员,保持版本更新。
* [SuperSandro2000](https://github.com/supersandro2000) - CI 负责人,维护者和 Factorio 监视程序的运行者。贡献版本更新并编写了 Travis 脚本。
* [DBendit](https://github.com/DBendit/docker_factorio_server) - 编写了管理员列表、禁止列表支持并贡献版本更新
* [Zopanix](https://github.com/zopanix/docker_factorio_server) - 原作者
* [Rfvgyhn](https://github.com/Rfvgyhn/docker-factorio) - 编写了随机生成的 RCON 密码
* [gnomus](https://github.com/gnomus/docker_factorio_server) - 编写了白名单支持
* [bplein](https://github.com/bplein/docker_factorio_server) - 编写了场景支持
* [jaredledvina](https://github.com/jaredledvina/docker_factorio_server) - 贡献版本更新
* [carlbennett](https://github.com/carlbennett) - 贡献版本更新和错误修复
[^1]: Space Age 模组也可以通过使用它们的名称(用空格分隔)来单独启用。
示例 1使用 `true` 启用所有
示例 2通过列出模组名称启用所有 `space-age elevated-rails quality`
示例 3仅启用 Elevated rails `elevated-rails`

128
build-rootless.py Executable file
View File

@ -0,0 +1,128 @@
#!/usr/bin/env python3
import os
import json
import subprocess
import shutil
import sys
import tempfile
PLATFORMS = [
"linux/arm64",
"linux/amd64",
]
def create_builder(build_dir, builder_name, platform):
check_exists_command = ["docker", "buildx", "inspect", builder_name]
if subprocess.run(check_exists_command, stderr=subprocess.DEVNULL).returncode != 0:
create_command = ["docker", "buildx", "create", "--platform", platform, "--name", builder_name]
try:
subprocess.run(create_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Creating builder failed")
exit(1)
def build_and_push_multiarch(build_dir, build_args, push):
builder_name = "factoriotools-rootless-multiarch"
platform=",".join(PLATFORMS)
create_builder(build_dir, builder_name, platform)
build_command = ["docker", "buildx", "build", "--platform", platform, "--builder", builder_name] + build_args
if push:
build_command.append("--push")
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build and push of rootless image failed")
exit(1)
def build_singlearch(build_dir, build_args):
build_command = ["docker", "build"] + build_args
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build of rootless image failed")
exit(1)
def push_singlearch(tags):
for tag in tags:
try:
subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
check=True)
except subprocess.CalledProcessError:
print("Docker push failed")
exit(1)
def build_and_push(sha256, version, tags, push, multiarch):
build_dir = tempfile.mktemp()
shutil.copytree("docker", build_dir)
# Use the rootless Dockerfile
build_args = ["-f", "Dockerfile.rootless", "--build-arg", f"VERSION={version}", "--build-arg", f"SHA256={sha256}", "."]
for tag in tags:
build_args.extend(["-t", f"factoriotools/factorio:{tag}"])
if multiarch:
build_and_push_multiarch(build_dir, build_args, push)
else:
build_singlearch(build_dir, build_args)
if push:
push_singlearch(tags)
def login():
try:
username = os.environ["DOCKER_USERNAME"]
password = os.environ["DOCKER_PASSWORD"]
subprocess.run(["docker", "login", "-u", username, "-p", password], check=True)
except KeyError:
print("Username and password need to be given")
exit(1)
except subprocess.CalledProcessError:
print("Docker login failed")
exit(1)
def generate_rootless_tags(original_tags):
"""Generate rootless-specific tags from original tags"""
rootless_tags = []
for tag in original_tags:
# Add -rootless suffix to each tag
rootless_tags.append(f"{tag}-rootless")
return rootless_tags
def main(push_tags=False, multiarch=False):
with open(os.path.join(os.path.dirname(__file__), "buildinfo.json")) as file_handle:
builddata = json.load(file_handle)
if push_tags:
login()
# Build only the latest stable and experimental versions for rootless
versions_to_build = []
# Find latest stable and experimental versions
for version, buildinfo in builddata.items():
if "stable" in buildinfo["tags"] or "latest" in buildinfo["tags"]:
versions_to_build.append((version, buildinfo))
for version, buildinfo in versions_to_build:
sha256 = buildinfo["sha256"]
original_tags = buildinfo["tags"]
rootless_tags = generate_rootless_tags(original_tags)
build_and_push(sha256, version, rootless_tags, push_tags, multiarch)
if __name__ == '__main__':
push_tags = False
multiarch = False
for arg in sys.argv[1:]:
if arg == "--push-tags":
push_tags = True
elif arg == "--multiarch":
multiarch = True
main(push_tags, multiarch)

109
build.py Executable file
View File

@ -0,0 +1,109 @@
#!/usr/bin/env python3
import os
import json
import subprocess
import shutil
import sys
import tempfile
PLATFORMS = [
"linux/arm64",
"linux/amd64",
]
def create_builder(build_dir, builder_name, platform):
check_exists_command = ["docker", "buildx", "inspect", builder_name]
if subprocess.run(check_exists_command, stderr=subprocess.DEVNULL).returncode != 0:
create_command = ["docker", "buildx", "create", "--platform", platform, "--name", builder_name]
try:
subprocess.run(create_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Creating builder failed")
exit(1)
def build_and_push_multiarch(build_dir, build_args, push):
builder_name = "factoriotools-multiarch"
platform=",".join(PLATFORMS)
create_builder(build_dir, builder_name, platform)
build_command = ["docker", "buildx", "build", "--platform", platform, "--builder", builder_name] + build_args
if push:
build_command.append("--push")
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build and push of image failed")
exit(1)
def build_singlearch(build_dir, build_args):
build_command = ["docker", "build"] + build_args
try:
subprocess.run(build_command, cwd=build_dir, check=True)
except subprocess.CalledProcessError:
print("Build of image failed")
exit(1)
def push_singlearch(tags):
for tag in tags:
try:
subprocess.run(["docker", "push", f"factoriotools/factorio:{tag}"],
check=True)
except subprocess.CalledProcessError:
print("Docker push failed")
exit(1)
def build_and_push(sha256, version, tags, push, multiarch):
build_dir = tempfile.mktemp()
shutil.copytree("docker", build_dir)
build_args = ["--build-arg", f"VERSION={version}", "--build-arg", f"SHA256={sha256}", "."]
for tag in tags:
build_args.extend(["-t", f"factoriotools/factorio:{tag}"])
if multiarch:
build_and_push_multiarch(build_dir, build_args, push)
else:
build_singlearch(build_dir, build_args)
if push:
push_singlearch(tags)
def login():
try:
username = os.environ["DOCKER_USERNAME"]
password = os.environ["DOCKER_PASSWORD"]
subprocess.run(["docker", "login", "-u", username, "-p", password], check=True)
except KeyError:
print("Username and password need to be given")
exit(1)
except subprocess.CalledProcessError:
print("Docker login failed")
exit(1)
def main(push_tags=False, multiarch=False):
with open(os.path.join(os.path.dirname(__file__), "buildinfo.json")) as file_handle:
builddata = json.load(file_handle)
if push_tags:
login()
for version, buildinfo in sorted(builddata.items(), key=lambda item: item[0], reverse=True):
sha256 = buildinfo["sha256"]
tags = buildinfo["tags"]
build_and_push(sha256, version, tags, push_tags, multiarch)
if __name__ == '__main__':
push_tags = False
multiarch = False
for arg in sys.argv[1:]:
if arg == "--push-tags":
push_tags = True
elif arg == "--multiarch":
multiarch = True
main(push_tags, multiarch)

View File

@ -101,6 +101,4 @@ if [[ $VERSION == "${BRANCH_VERSION:-}" && ${GITHUB_BASE_REF:-} == "" ]] ||
if [[ ${STABLE:-} == "$VERSION" ]]; then
docker push "$DOCKER_REPO:stable"
fi
curl -X POST https://hooks.microbadger.com/images/factoriotools/factorio/TmmKGNp8jKcFqZvcJhTCIAJVluw=
fi

363
buildinfo.json Normal file
View File

@ -0,0 +1,363 @@
{
"0.12.35": {
"sha256": "ab9cf01a56dde3073aaaa5152c628bbf9a5bb85638b87dc3d7fdb77fb169aedd",
"tags": [
"0.12.35",
"0.12"
]
},
"0.13.20": {
"sha256": "cbf5481e4b7e0efcc07c7b6a1fc3ff1404ad5597f3c9d37914a52ffb58d7c159",
"tags": [
"0.13.20",
"0.13"
]
},
"0.14.23": {
"sha256": "96c3e7acd4e0f066a499baba01823cac7c1caf0e50dbddcea5793f57bd60dc8c",
"tags": [
"0.14.23",
"0.14"
]
},
"0.15.40": {
"sha256": "1041ef61ea4aecd1f425e6030a909f0c349a9c01d1b3324d84a61b1cfef5ba6c",
"tags": [
"0.15.40",
"0.15"
]
},
"0.16.51": {
"sha256": "6cb09f5ac87f16f8d5b43cef26c0ae26cc46a57a0382e253dfda032dc5bb367f",
"tags": [
"0.16.51",
"0.16"
]
},
"0.17.79": {
"sha256": "9ace12fa986df028dc1851bf4de2cb038044d743e98823bc1c48ba21aa4d23df",
"tags": [
"0.17.79",
"0.17"
]
},
"1.0.0": {
"sha256": "81d9e1aa94435aeec4131c8869fa6e9331726bea1ea31db750b65ba42dbd1464",
"tags": [
"1.0.0",
"1.0"
]
},
"1.1.110": {
"sha256": "485fe6db36e5decd7dd0d70e7c97e61f818100fa3e48d87884b287027c7a646a",
"tags": [
"stable-1.1.110",
"1",
"1.1",
"1.1.110"
]
},
"2.0.13": {
"sha256": "27b36901a39e593adf28418c0286142c6c7a9f83d156963c7369bd405a25c7d1",
"tags": [
"stable-2.0.13",
"2.0",
"2.0.13"
]
},
"2.0.14": {
"sha256": "5a4bc4c3b2a97ed1fc58eb796321e848dcc64435bd91013dd9c78a14a8ce8815",
"tags": [
"stable-2.0.14",
"2.0",
"2.0.14"
]
},
"2.0.15": {
"sha256": "70b441cb807811a60586c01107248c1d8d7ae043bd1f23675fc924fbaaa538d8",
"tags": [
"stable-2.0.15",
"2.0",
"2.0.15"
]
},
"2.0.16": {
"sha256": "f2069b4b746500d945eeb67ef7eda5e7aebe7fd0294c2af4e117af22a3bbaea3",
"tags": [
"2.0.16"
]
},
"2.0.17": {
"sha256": "183407f2fb21e05152442ffb5f15ffb283994339ca6a51b3559a257c30505e5e",
"tags": [
"2.0.17"
]
},
"2.0.18": {
"sha256": "f378a1dc8a545c13d8ca616cbe72d245aa3ce93e3f219d8d60d3c06c7df82dc0",
"tags": [
"2.0.18"
]
},
"2.0.19": {
"sha256": "2e27aca3a7f65b50916d14a62203b6861cbe657e8d2dbd8f813e0a606efce9c7",
"tags": [
"2.0.19"
]
},
"2.0.20": {
"sha256": "c4a901f2f1dbedbb41654560db4c6fab683a30c20334e805d4ef740c0416515a",
"tags": [
"stable-2.0.20",
"2.0",
"2.0.20"
]
},
"2.0.21": {
"sha256": "1d6d2785006d6a8d9d5fdcdaa7097a189ec35ba95f3521025dc4e046f7a1398e",
"tags": [
"stable-2.0.21",
"2.0",
"2.0.21"
]
},
"2.0.22": {
"sha256": "14c3eea7600fbe7f35bca52fe4c277e8f5e23b34c35ebebaa46c6752c750cb85",
"tags": [
"2.0.22"
]
},
"2.0.23": {
"sha256": "e819fc9ad6df061bf9d4bffc91988dd18d0e3982c8b1c22c0525d78bda3ef216",
"tags": [
"stable-2.0.23",
"2.0",
"2.0.23"
]
},
"2.0.24": {
"sha256": "4644acc4195391fe19a7468c546d10a494ce1a188964c79f20cb0fa050b67120",
"tags": [
"2.0.24"
]
},
"2.0.25": {
"sha256": "0d1698f1f29759ff27faa6a5d9c3804377cb1767f2692003a8e9d4c294845e5a",
"tags": [
"2.0.25"
]
},
"2.0.26": {
"sha256": "a401024039372a53b9a29b7deb4ac279cd9a34abe69426a109a13a9a1c599f1f",
"tags": [
"2.0.26"
]
},
"2.0.27": {
"sha256": "63c75ce74cd9d1e4b65ae9f98e9865abdbe3d600fb3259dcda5ea69a512b2993",
"tags": [
"2.0.27"
]
},
"2.0.28": {
"sha256": "ea9937b6adc7a18e17a4e1e64992ec389407497b36e68280bb14fcdd4c884dd3",
"tags": [
"stable-2.0.28",
"2.0",
"2.0.28"
]
},
"2.0.29": {
"sha256": "54088c9cacfddbce2e7bf90604fea095ff723e70d9bb056e1fb469b900a50f09",
"tags": [
"2.0.29"
]
},
"2.0.30": {
"sha256": "4137824a20e1f3298410432c85e62d0eb46b0dab1a8411c233699f890d4c1668",
"tags": [
"stable-2.0.30",
"2.0",
"2.0.30"
]
},
"2.0.31": {
"sha256": "0ee39ff6181ef41b606b7ba1ab5c04d8f81579ef56ec4947e4d74ce5d192b5d5",
"tags": [
"2.0.31"
]
},
"2.0.32": {
"sha256": "2a6102ae42dcc5e8fe923bd68bcd326a569e35912acde121301e5d4d2d856417",
"tags": [
"stable-2.0.32",
"2.0",
"2.0.32"
]
},
"2.0.33": {
"sha256": "9365a34d1724e5c9f592cc9da511485e2fa7da1c12df08029bce478586ba4b7b",
"tags": [
"2.0.33"
]
},
"2.0.34": {
"sha256": "9511462203ebb2763f9f8623bb17f3070041ae3cbd7d80284c1e9bb38c09fc40",
"tags": [
"2.0.34"
]
},
"2.0.35": {
"sha256": "31cd58eaf4b06cc0dc5d82640f7adf2366aa9da64133d2c228f1308f1060a990",
"tags": [
"2.0.35"
]
},
"2.0.36": {
"sha256": "e94567b986654f1f7c3ec5c8bd151e3768b4ab9ab9cc389f6b9fd8e0dab32ce2",
"tags": [
"2.0.36"
]
},
"2.0.37": {
"sha256": "5f105131fe4f48d47fd813f57b6bd275840a47b21e39b30d22bf5da30075a786",
"tags": [
"2.0.37"
]
},
"2.0.38": {
"sha256": "ad9650f7456aecc8adb5369eedb418507c7643bede0da60fc1a239878d4902de",
"tags": [
"2.0.38"
]
},
"2.0.39": {
"sha256": "0f8a3d0e43797b5ff4d8b85d7c334b095a3f07d9aa7f80b1e87f94939a93df34",
"tags": [
"stable-2.0.39",
"2.0",
"2.0.39"
]
},
"2.0.40": {
"sha256": "eac1f24afb68acbfcf1d72d2ad142e8584d77f2d100a3af743f106e50ac176d3",
"tags": [
"2.0.40"
]
},
"2.0.41": {
"sha256": "77ebccae8167fc1a9fc4da8c11e8410f6017b92b1a0913eb58ac5285c9eec399",
"tags": [
"stable-2.0.41",
"2.0",
"2.0.41"
]
},
"2.0.42": {
"sha256": "b5b8b8bdc915e67dbc1710cd3d6aa6802d397b7c0f47db07da8acf39d5bd6376",
"tags": [
"stable-2.0.42",
"2.0",
"2.0.42"
]
},
"2.0.43": {
"sha256": "bde6e167330c4439ce7df3ac519ea445120258ef676f1f6ad31d0c2816d3aee3",
"tags": [
"stable-2.0.43",
"2.0",
"2.0.43"
]
},
"2.0.44": {
"sha256": "9468c5e07080c01eb7a734036160bf806d62cafc11465a23150cfbd210e1036d",
"tags": [
"2.0.44"
]
},
"2.0.45": {
"sha256": "4fd7e04bb3ea7d12da8e1c3befc6b53b3c0064775c960a5a9db6a943f2259fc2",
"tags": [
"2.0.45"
]
},
"2.0.46": {
"sha256": "fc611b6d4078b5d9448284c2890f7e0b6b1f203d52f622c655d3600982489c3e",
"tags": [
"2.0.46"
]
},
"2.0.47": {
"sha256": "f0f320c77616a4794227eb637a70b557108f3141a4633276593220a768f49a26",
"tags": [
"stable-2.0.47",
"2.0",
"2.0.47"
]
},
"2.0.48": {
"sha256": "f0038835e96bbacc19d52d22d47469882d9ebe41a4e5213c0471020647a1ee2d",
"tags": [
"2.0.48"
]
},
"2.0.49": {
"sha256": "ef0648ca1ba44c145a3a3e4c174ccd276eb4a335155a20df1ae0e47156fa34ff",
"tags": [
"2.0.49"
]
},
"2.0.50": {
"sha256": "81d4aec735473c5bd2c87f09abcd793c31cb9a07d9fdf3c3d7275c78ebe4bc18",
"tags": [
"2.0.50"
]
},
"2.0.51": {
"sha256": "fc940dea67d25d3fd403531520e8afda2779ff1fa8050f535ac1351b7873a070",
"tags": [
"2.0.51"
]
},
"2.0.52": {
"sha256": "be8d6216890089890693d6d94f141f745d35c53e52c6b942f6c944f5c00c8c26",
"tags": [
"2.0.52"
]
},
"2.0.53": {
"sha256": "40a57076f80dbee0238dab62f16585def06f7d7e5b41f6b677be41b4d2cae811",
"tags": [
"2.0.53"
]
},
"2.0.54": {
"sha256": "ad47c541b70763552bcf597202ee84aaac727d0ba158873134dc163a3a0506f0",
"tags": [
"2.0.54"
]
},
"2.0.55": {
"sha256": "ef12a54d1556ae1f84ff99edc23706d13b7ad41f1c02d74ca1dfadf9448fcbae",
"tags": [
"stable-2.0.55",
"2",
"2.0",
"2.0.55",
"stable"
]
},
"2.0.57": {
"sha256": "22b232afb77067c68a3afe087be6a0ee760479262598a12a709e1b03ea9508a6",
"tags": [
"2.0.57"
]
},
"2.0.58": {
"sha256": "be82e1aeba4169420e1b00c12a3e00ec2309a41327f9d6c335feec27bbc885e6",
"tags": [
"latest",
"2.0.58"
]
}
}

38
docker-compose.yml Normal file
View File

@ -0,0 +1,38 @@
version: "2"
services:
factorio:
container_name: factorio
image: factoriotools/factorio:stable
restart: unless-stopped
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- ./data:/factorio
environment:
- UPDATE_MODS_ON_START=true
# Uncomment to enable autoupdate via watchtower
#labels:
# # Labels to allow watchtower autoupdate only if no players are online
# - com.centurylinklabs.watchtower.enable=true
# - com.centurylinklabs.watchtower.scope=factorio
# - com.centurylinklabs.watchtower.lifecycle.pre-update="/players-online.sh"
# Uncomment the following files to use watchtower for updating the factorio container
# Full documentation of watchtower: https://github.com/containrrr/watchtower
#watchtower:
# container_name: watchtower_factorio
# image: containrrr/watchtower
# restart: unless-stopped
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock
# environment:
# # Only update containers which have the option 'watchtower.enable=true' set
# - WATCHTOWER_TIMEOUT=30s
# - WATCHTOWER_LABEL_ENABLE=true
# - WATCHTOWER_POLL_INTERVAL=3600
# - WATCHTOWER_LIFECYCLE_HOOKS=true
# - WATCHTOWER_SCOPE=factorio
# labels:
# - com.centurylinklabs.watchtower.scope=factorio

97
docker/Dockerfile Executable file
View File

@ -0,0 +1,97 @@
# build rcon client
FROM debian:stable-slim AS rcon-builder
RUN apt-get -q update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install build-essential
WORKDIR /src
COPY rcon/ /src
RUN make
# build factorio image
FROM debian:stable-slim
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG USER=factorio
ARG GROUP=factorio
ARG PUID=845
ARG PGID=845
ARG BOX64_VERSION=v0.2.4
# optionally utilize a built-in map-gen-preset (see data/base/prototypes/map-gen-presets
# if this is used, the preset will be used over any .json files supplied
# vanilla factorio provides the following presets:
# rich-resources, marathon, death-world, death-world-marathon, rail-world, ribbon-world, island
# a modded factorio example for using this:
# space-exploration
ARG PRESET
# number of retries that curl will use when pulling the headless server tarball
ARG CURL_RETRIES=8
ENV PORT=34197 \
RCON_PORT=27015 \
SAVES=/factorio/saves \
PRESET="$PRESET" \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
PUID="$PUID" \
PGID="$PGID" \
DLC_SPACE_AGE="true"
SHELL ["/bin/bash", "-eo", "pipefail", "-c"]
RUN apt-get -q update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install ca-certificates curl jq pwgen xz-utils procps gettext-base --no-install-recommends \
&& if [[ "$(uname -m)" == "aarch64" ]]; then \
echo "installing ARM compatability layer" \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install unzip --no-install-recommends \
&& curl -LO https://github.com/ptitSeb/box64/releases/download/${BOX64_VERSION}/box64-GENERIC_ARM-RelWithDebInfo.zip \
&& unzip box64-GENERIC_ARM-RelWithDebInfo.zip -d /bin \
&& rm -f box64-GENERIC_ARM-RelWithDebInfo.zip \
&& chmod +x /bin/box64; \
fi \
&& rm -rf /var/lib/apt/lists/*
RUN addgroup --system --gid "$PGID" "$GROUP" \
&& adduser --system --uid "$PUID" --gid "$PGID" --no-create-home --disabled-password --shell /bin/sh "$USER"
# version checksum of the archive to download
ARG VERSION
ARG SHA256
LABEL factorio.version=${VERSION}
ENV VERSION=${VERSION} \
SHA256=${SHA256}
RUN set -ox pipefail \
&& if [[ "${VERSION}" == "" ]]; then \
echo "build-arg VERSION is required" \
&& exit 1; \
fi \
&& if [[ "${SHA256}" == "" ]]; then \
echo "build-arg SHA256 is required" \
&& exit 1; \
fi \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" --retry $CURL_RETRIES \
&& echo "$SHA256 $archive" | sha256sum -c \
|| (sha256sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/ \
&& chown -R "$USER":"$GROUP" /opt/factorio /factorio
COPY files/*.sh /
COPY files/config.ini /opt/factorio/config/config.ini
COPY --from=rcon-builder /src/rcon /bin/rcon
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -0,0 +1,93 @@
# build rcon client
FROM debian:stable-slim AS rcon-builder
RUN apt-get -q update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install build-essential
WORKDIR /src
COPY rcon/ /src
RUN make
# build factorio image
FROM debian:stable-slim
LABEL maintainer="https://github.com/factoriotools/factorio-docker"
ARG BOX64_VERSION=v0.2.4
# optionally utilize a built-in map-gen-preset (see data/base/prototypes/map-gen-presets
ARG PRESET
# number of retries that curl will use when pulling the headless server tarball
ARG CURL_RETRIES=8
ENV PORT=34197 \
RCON_PORT=27015 \
SAVES=/factorio/saves \
PRESET="$PRESET" \
CONFIG=/factorio/config \
MODS=/factorio/mods \
SCENARIOS=/factorio/scenarios \
SCRIPTOUTPUT=/factorio/script-output \
DLC_SPACE_AGE="true"
SHELL ["/bin/bash", "-eo", "pipefail", "-c"]
RUN apt-get -q update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install ca-certificates curl jq pwgen xz-utils procps gettext-base --no-install-recommends \
&& if [[ "$(uname -m)" == "aarch64" ]]; then \
echo "installing ARM compatability layer" \
&& DEBIAN_FRONTEND=noninteractive apt-get -qy install unzip --no-install-recommends \
&& curl -LO https://github.com/ptitSeb/box64/releases/download/${BOX64_VERSION}/box64-GENERIC_ARM-RelWithDebInfo.zip \
&& unzip box64-GENERIC_ARM-RelWithDebInfo.zip -d /bin \
&& rm -f box64-GENERIC_ARM-RelWithDebInfo.zip \
&& chmod +x /bin/box64; \
fi \
&& rm -rf /var/lib/apt/lists/*
# version checksum of the archive to download
ARG VERSION
ARG SHA256
LABEL factorio.version=${VERSION}
ENV VERSION=${VERSION} \
SHA256=${SHA256}
RUN set -ox pipefail \
&& if [[ "${VERSION}" == "" ]]; then \
echo "build-arg VERSION is required" \
&& exit 1; \
fi \
&& if [[ "${SHA256}" == "" ]]; then \
echo "build-arg SHA256 is required" \
&& exit 1; \
fi \
&& archive="/tmp/factorio_headless_x64_$VERSION.tar.xz" \
&& mkdir -p /opt /factorio \
&& curl -sSL "https://www.factorio.com/get-download/$VERSION/headless/linux64" -o "$archive" --retry $CURL_RETRIES \
&& echo "$SHA256 $archive" | sha256sum -c \
|| (sha256sum "$archive" && file "$archive" && exit 1) \
&& tar xf "$archive" --directory /opt \
&& chmod ugo=rwx /opt/factorio \
&& rm "$archive" \
&& ln -s "$SCENARIOS" /opt/factorio/scenarios \
&& ln -s "$SAVES" /opt/factorio/saves \
&& mkdir -p /opt/factorio/config/
COPY files/*.sh /
COPY files/docker-entrypoint-rootless.sh /docker-entrypoint.sh
COPY files/config.ini /opt/factorio/config/config.ini
COPY --from=rcon-builder /src/rcon /bin/rcon
# Make all scripts executable
RUN chmod +x /*.sh
# Set proper permissions for the factorio directory
RUN chmod -R 777 /opt/factorio /factorio
VOLUME /factorio
EXPOSE $PORT/udp $RCON_PORT/tcp
# Run as non-root user (UID 1000 is common for the first user in rootless containers)
USER 1000:1000
ENTRYPOINT ["/docker-entrypoint.sh"]

28
docker/docker-compose.yml Normal file
View File

@ -0,0 +1,28 @@
version: '2'
services:
factorio:
build:
context: .
args:
# Check buildinfo.json for supported versions and SHAs
# https://github.com/factoriotools/factorio-docker/blob/master/buildinfo.json
- VERSION=2.0.55
- SHA256=ef12a54d1556ae1f84ff99edc23706d13b7ad41f1c02d74ca1dfadf9448fcbae
ports:
- "34197:34197/udp"
- "27015:27015/tcp"
volumes:
- /opt/factorio:/factorio
# environment:
# - PUID=1000
# - PGID=1000
# - UPDATE_MODS_ON_START=true
# - USERNAME=FactorioUsername
# - TOKEN=FactorioToken
# - PORT=34198
# - PRESET=deathworld
# - ADDR=::1
# # Uncomment the following line to enable the use of the host's network stack,
# # which may be necessary for some setups like NAS or when using some proxy service like firewall rules.
# extra_hosts:
# - "host.docker.internal:host-gateway"

57
docker/files/docker-dlc.sh Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
set -eou pipefail
# Path to the mod-list.json file
MOD_LIST_FILE="$MODS/mod-list.json"
ALL_SPACE_AGE_MODS=("elevated-rails" "quality" "space-age")
if [[ ! -f "$MOD_LIST_FILE" ]]; then
# Create the mod-list.json file if it doesn't exist
echo '{"mods":[{"name":"base","enabled":true}]}' > "$MOD_LIST_FILE"
fi
enable_mod()
{
echo "Enable mod $1 for DLC"
jq --arg mod_name "$1" 'if .mods | map(.name) | index($mod_name) then .mods |= map(if .name == $mod_name and .enabled == false then .enabled = true else . end) else . end' "$MOD_LIST_FILE" > "$MOD_LIST_FILE.tmp"
mv "$MOD_LIST_FILE.tmp" "$MOD_LIST_FILE"
}
disable_mod()
{
echo "Disable mod $1 for DLC"
jq --arg mod_name "$1" 'if .mods | map(.name) | index($mod_name) then .mods |= map(if .name == $mod_name and .enabled == true then .enabled = false else . end) else .mods += [{"name": $mod_name, "enabled": false}] end' "$MOD_LIST_FILE" > "$MOD_LIST_FILE.tmp"
mv "$MOD_LIST_FILE.tmp" "$MOD_LIST_FILE"
}
# Enable or disable DLCs if configured
if [[ ${DLC_SPACE_AGE:-} == "true" ]]; then
# Define the DLC mods
ENABLE_MODS=(${ALL_SPACE_AGE_MODS[@]})
elif [[ ${DLC_SPACE_AGE:-} == "false" ]]; then
# Define the DLC mods
DISABLE_MODS=(${ALL_SPACE_AGE_MODS[@]})
else
ENABLE_MODS=()
DISABLE_MODS=()
for SPACE_AGE_MOD in "${ALL_SPACE_AGE_MODS[@]}"; do
REGEX="(^|\s)$SPACE_AGE_MOD($|\s)"
if [[ "$DLC_SPACE_AGE" =~ $REGEX ]]; then
ENABLE_MODS+=($SPACE_AGE_MOD)
else
DISABLE_MODS+=($SPACE_AGE_MOD)
fi
done
fi
# Iterate over each DLC mod to enable
for MOD in "${ENABLE_MODS[@]}"; do
enable_mod "$MOD"
done
# Iterate over each DLC mod to disable
for MOD in "${DISABLE_MODS[@]}"; do
disable_mod "$MOD"
done

View File

@ -1,11 +1,16 @@
#!/bin/bash
set -eoux pipefail
INSTALLED_DIRECTORY=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
FACTORIO_VOL=/factorio
LOAD_LATEST_SAVE="${LOAD_LATEST_SAVE:-true}"
GENERATE_NEW_SAVE="${GENERATE_NEW_SAVE:-false}"
PRESET="${PRESET:-""}"
SAVE_NAME="${SAVE_NAME:-""}"
BIND="${BIND:-""}"
CONSOLE_LOG_LOCATION="${CONSOLE_LOG_LOCATION:-""}"
# Create directories if they don't exist
# In rootless mode, these should be writable by the container user
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
@ -13,13 +18,13 @@ mkdir -p "$MODS"
mkdir -p "$SCENARIOS"
mkdir -p "$SCRIPTOUTPUT"
# Generate RCON password if needed
if [[ ! -f $CONFIG/rconpw ]]; then
# Generate a new RCON password if none exists
pwgen 15 1 >"$CONFIG/rconpw"
fi
# Copy default configs if they don't exist
if [[ ! -f $CONFIG/server-settings.json ]]; then
# Copy default settings if server-settings.json doesn't exist
cp /opt/factorio/data/server-settings.example.json "$CONFIG/server-settings.json"
fi
@ -31,30 +36,32 @@ if [[ ! -f $CONFIG/map-settings.json ]]; then
cp /opt/factorio/data/map-settings.example.json "$CONFIG/map-settings.json"
fi
# Clean up incomplete saves
NRTMPSAVES=$( find -L "$SAVES" -iname \*.tmp.zip -mindepth 1 | wc -l )
if [[ $NRTMPSAVES -gt 0 ]]; then
# Delete incomplete saves (such as after a forced exit)
rm -f "$SAVES"/*.tmp.zip
fi
# Update mods if requested
if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
${INSTALLED_DIRECTORY}/docker-update-mods.sh
fi
if [[ $(id -u) = 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
# Handle DLC
${INSTALLED_DIRECTORY}/docker-dlc.sh
# In rootless mode, we don't need to handle user switching or chown
# The container runs as the specified user from the start
EXEC=""
if [[ -f /bin/box64 ]]; then
# Use emulator for ARM hosts
EXEC="/bin/box64"
fi
# Update config path
sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
# Generate new save if needed
NRSAVES=$(find -L "$SAVES" -iname \*.zip -mindepth 1 | wc -l)
if [[ $GENERATE_NEW_SAVE != true && $NRSAVES == 0 ]]; then
GENERATE_NEW_SAVE=true
@ -69,13 +76,22 @@ if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
if [[ ! -z "$PRESET" ]]; then
$EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--preset "$PRESET" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
else
$EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
fi
fi
# Build command flags
FLAGS=(\
--port "$PORT" \
--server-settings "$CONFIG/server-settings.json" \
@ -86,13 +102,23 @@ FLAGS=(\
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json \
--mod-directory "$MODS" \
)
if [ -n "$CONSOLE_LOG_LOCATION" ]; then
FLAGS+=( --console-log "$CONSOLE_LOG_LOCATION" )
fi
if [ -n "$BIND" ]; then
FLAGS+=( --bind "$BIND" )
fi
if [[ $LOAD_LATEST_SAVE == true ]]; then
FLAGS+=( --start-server-load-latest )
else
FLAGS+=( --start-server "$SAVE_NAME" )
fi
# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"
# Execute factorio
# In rootless mode, we run directly without user switching
exec $EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"

View File

@ -1,10 +1,13 @@
#!/bin/bash
set -eoux pipefail
INSTALLED_DIRECTORY=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
FACTORIO_VOL=/factorio
LOAD_LATEST_SAVE="${LOAD_LATEST_SAVE:-true}"
GENERATE_NEW_SAVE="${GENERATE_NEW_SAVE:-false}"
PRESET="${PRESET:-""}"
SAVE_NAME="${SAVE_NAME:-""}"
BIND="${BIND:-""}"
CONSOLE_LOG_LOCATION="${CONSOLE_LOG_LOCATION:-""}"
mkdir -p "$FACTORIO_VOL"
mkdir -p "$SAVES"
@ -38,19 +41,25 @@ if [[ $NRTMPSAVES -gt 0 ]]; then
fi
if [[ ${UPDATE_MODS_ON_START:-} == "true" ]]; then
./docker-update-mods.sh
${INSTALLED_DIRECTORY}/docker-update-mods.sh
fi
if [[ $(id -u) = 0 ]]; then
${INSTALLED_DIRECTORY}/docker-dlc.sh
EXEC=""
if [[ $(id -u) == 0 ]]; then
# Update the User and Group ID based on the PUID/PGID variables
usermod -o -u "$PUID" factorio
groupmod -o -g "$PGID" factorio
# Take ownership of factorio data if running as root
chown -R factorio:factorio "$FACTORIO_VOL"
# Drop to the factorio user
SU_EXEC="su-exec factorio"
else
SU_EXEC=""
EXEC="runuser -u factorio -g factorio --"
fi
if [[ -f /bin/box64 ]]; then
# Use an emulator to run on ARM hosts
# this only gets installed when the target docker platform is linux/arm64
EXEC="$EXEC /bin/box64"
fi
sed -i '/write-data=/c\write-data=\/factorio/' /opt/factorio/config/config.ini
@ -69,11 +78,19 @@ if [[ $GENERATE_NEW_SAVE == true ]]; then
if [[ -f "$SAVES/$SAVE_NAME.zip" ]]; then
echo "Map $SAVES/$SAVE_NAME.zip already exists, skipping map generation"
else
$SU_EXEC /opt/factorio/bin/x64/factorio \
if [[ ! -z "$PRESET" ]]; then
$EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--preset "$PRESET" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
else
$EXEC /opt/factorio/bin/x64/factorio \
--create "$SAVES/$SAVE_NAME.zip" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json"
fi
fi
fi
FLAGS=(\
@ -86,8 +103,17 @@ FLAGS=(\
--server-adminlist "$CONFIG/server-adminlist.json" \
--rcon-password "$(cat "$CONFIG/rconpw")" \
--server-id /factorio/config/server-id.json \
--mod-directory "$MODS" \
)
if [ -n "$CONSOLE_LOG_LOCATION" ]; then
FLAGS+=( --console-log "$CONSOLE_LOG_LOCATION" )
fi
if [ -n "$BIND" ]; then
FLAGS+=( --bind "$BIND" )
fi
if [[ $LOAD_LATEST_SAVE == true ]]; then
FLAGS+=( --start-server-load-latest )
else
@ -95,4 +121,4 @@ else
fi
# shellcheck disable=SC2086
exec $SU_EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"
exec $EXEC /opt/factorio/bin/x64/factorio "${FLAGS[@]}" "$@"

11
docker/files/players-online.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
PLAYERS=$(rcon /players)
ONLINE_COUNT=$(echo "$PLAYERS" | grep -c " (online)$")
if [[ "$ONLINE_COUNT" -gt "0" ]]; then
echo "$PLAYERS"
# exit with 75 (EX_TEMPFAIL) so watchtower skips the update
# https://containrrr.dev/watchtower/lifecycle-hooks/
exit 75
fi

View File

@ -6,6 +6,8 @@ if [[ -z ${1:-} ]]; then
fi
SERVER_SCENARIO="$1"
PRESET="${PRESET:-""}"
mkdir -p "$SAVES"
mkdir -p "$CONFIG"
mkdir -p "$MODS"
@ -32,6 +34,7 @@ fi
exec /opt/factorio/bin/x64/factorio \
--port "$PORT" \
--start-server-load-scenario "$SERVER_SCENARIO" \
--preset "$PRESET" \
--map-gen-settings "$CONFIG/map-gen-settings.json" \
--map-settings "$CONFIG/map-settings.json" \
--server-settings "$CONFIG/server-settings.json" \

223
docker/files/update-mods.sh Executable file
View File

@ -0,0 +1,223 @@
#!/bin/bash
set -eou pipefail
FACTORIO_VERSION=$1
MOD_DIR=$2
USERNAME=$3
TOKEN=$4
MOD_BASE_URL="https://mods.factorio.com"
print_step()
{
echo "$1"
}
print_success()
{
echo "$1"
}
print_failure()
{
echo "$1"
}
# Checks game version vs version in mod.
# Returns 0 if major version differs or mod minor version is less than game version, 1 if ok
check_game_version() {
local game_version="$1"
local mod_version="$2"
local game_major mod_major game_minor mod_minor
game_major=$(echo "$game_version" | cut -d '.' -f1)
game_minor=$(echo "$game_version" | cut -d '.' -f2)
mod_major=$(echo "$mod_version" | cut -d '.' -f1)
mod_minor=$(echo "$mod_version" | cut -d '.' -f2)
if [[ "$game_major" -ne "$mod_major" ]]; then
echo 0
return
fi
if [[ "$mod_minor" -ge "$game_minor" ]]; then
echo 1
else
echo 0
fi
}
# Checks dependency string with provided version.
# Only checks for operator based string, ignoring everything else
# Returns 1 if check is ok, 0 if not
check_dependency_version()
{
local dependency="$1"
local mod_version="$2"
if [[ "$dependency" =~ ^(\?|!|~|\(~\)) ]]; then
echo 1
fi
local condition
condition=$(echo "$dependency" | grep -oE '(>=|<=|>|<|=) [0-9]+(\.[0-9]+)*')
if [[ -z "$condition" ]]; then
echo 1
fi
local operator required_version
operator=$(echo "$condition" | awk '{print $1}')
required_version=$(echo "$condition" | awk '{print $2}')
case "$operator" in
">=")
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | head -n1)" == "$required_version" ]]; then
echo 1
else
echo 0
fi
;;
">")
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | head -n1)" == "$required_version" && "$required_version" != "$FACTORIO_VERSION" ]]; then
echo 1
else
echo 0
fi
;;
"<=")
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | tail -n1)" == "$required_version" ]]; then
echo 1
else
echo 0
fi
;;
"<")
if [[ "$(printf '%s\n%s\n' "$required_version" "$mod_version" | sort -V | tail -n1)" == "$required_version" && "$required_version" != "$FACTORIO_VERSION" ]]; then
echo 1
else
echo 0
fi
;;
"=")
if [[ "$mod_version" == "$required_version" ]]; then
echo 1
else
echo 0
fi
;;
*)
echo 0
;;
esac
}
get_mod_info()
{
local mod_info_json="$1"
while IFS= read -r mod_release_info; do
local mod_version mod_factorio_version
mod_version=$(echo "$mod_release_info" | jq -r ".version")
mod_factorio_version=$(echo "$mod_release_info" | jq -r ".info_json.factorio_version")
if [[ $(check_game_version "$mod_factorio_version" "$FACTORIO_VERSION") == 0 ]]; then
echo " Skipping mod version $mod_version because of factorio version mismatch" >&2
continue
fi
# If we found 'dependencies' element, we also check versions there
if [[ $(echo "$mod_release_info" | jq -e '.info_json | has("dependencies") and (.dependencies | length > 0)') == true ]]; then
while IFS= read -r dependency; do
# We only check for 'base' dependency
if [[ "$dependency" == base* ]] && [[ $(check_dependency_version "$dependency" "$FACTORIO_VERSION") == 0 ]]; then
echo " Skipping mod version $mod_version, unsatisfied base dependency: $dependency" >&2
continue 2
fi
done < <(echo "$mod_release_info" | jq -r '.info_json.dependencies[]')
fi
echo "$mod_release_info" | jq -j ".file_name, \";\", .download_url, \";\", .sha1"
break
done < <(echo "$mod_info_json" | jq -c ".releases|sort_by(.released_at)|reverse|.[]")
}
update_mod()
{
MOD_NAME="$1"
MOD_NAME_ENCODED="${1// /%20}"
print_step "Checking for update of mod $MOD_NAME for factorio $FACTORIO_VERSION ..."
MOD_INFO_URL="$MOD_BASE_URL/api/mods/$MOD_NAME_ENCODED/full"
MOD_INFO_JSON=$(curl --silent "$MOD_INFO_URL")
if ! echo "$MOD_INFO_JSON" | jq -e .name >/dev/null; then
print_success " Custom mod not on $MOD_BASE_URL, skipped."
return 0
fi
MOD_INFO=$(get_mod_info "$MOD_INFO_JSON")
if [[ "$MOD_INFO" == "" ]]; then
print_failure " Not compatible with version"
return 0
fi
MOD_FILENAME=$(echo "$MOD_INFO" | cut -f1 -d";")
MOD_URL=$(echo "$MOD_INFO" | cut -f2 -d";")
MOD_SHA1=$(echo "$MOD_INFO" | cut -f3 -d";")
if [[ $MOD_FILENAME == null ]]; then
print_failure " Not compatible with version"
return 0
fi
if [[ -f $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Already up-to-date."
return 0
fi
print_step " Downloading $MOD_FILENAME"
FULL_URL="$MOD_BASE_URL$MOD_URL?username=$USERNAME&token=$TOKEN"
HTTP_STATUS=$(curl --silent -L -w "%{http_code}" -o "$MOD_DIR/$MOD_FILENAME" "$FULL_URL")
if [[ $HTTP_STATUS != 200 ]]; then
print_failure " Download failed: Code $HTTP_STATUS."
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
if [[ ! -f $MOD_DIR/$MOD_FILENAME ]]; then
print_failure " Downloaded file missing!"
return 1
fi
if ! [[ $(sha1sum "$MOD_DIR/$MOD_FILENAME") =~ $MOD_SHA1 ]]; then
print_failure " SHA1 mismatch!"
rm -f "$MOD_DIR/$MOD_FILENAME"
return 1
fi
print_success " Download complete."
for file in "$MOD_DIR/${MOD_NAME}_"*".zip"; do # wildcard does usually not work in quotes: https://unix.stackexchange.com/a/67761
if [[ $file != $MOD_DIR/$MOD_FILENAME ]]; then
print_success " Deleting old version: $file"
rm -f "$file"
fi
done
return 0
}
if [[ -f $MOD_DIR/mod-list.json ]]; then
jq -r ".mods|map(select(.enabled))|.[].name" "$MOD_DIR/mod-list.json" | while read -r mod; do
if [[ $mod != base ]]; then
update_mod "$mod" || true
fi
done
fi

13
docker/rcon/Makefile Normal file
View File

@ -0,0 +1,13 @@
# Optimization
OPT = -O3 -flto
TARGET = rcon
CC = gcc
CFLAGS = -std=c17 -Wall -Wextra -pedantic $(OPT)
REMOVE = rm -f
all:
$(CC) $(CFLAGS) main.c -o $(TARGET)
clean:
$(REMOVE) $(TARGET)

217
docker/rcon/main.c Normal file
View File

@ -0,0 +1,217 @@
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#define MIN_PACKET 10
#define MAX_PACKET 4096
#define MAX_BODY (MAX_PACKET - (3 * sizeof(uint32_t)) - 2)
#define RCON_HOST "127.0.0.1"
typedef enum {
RCON_TYPE_RESPONSE = 0,
RCON_TYPE_EXECCOMMAND = 2,
RCON_TYPE_AUTH_RESPONSE = 2,
RCON_TYPE_AUTH = 3,
} packet_type;
typedef struct {
uint32_t length;
uint32_t id;
packet_type type;
char body[MAX_BODY];
} packet;
int rcon_open(const char *port);
void rcon_create(packet* pkt, packet_type type, const char* body);
bool rcon_send(int rcon_socket, const packet* pkt);
bool rcon_auth(int rcon_socket, const char* password);
bool rcon_recv(int rcon_socket, packet* pkt, packet_type expected_type);
char* combine_args(int argc, char* argv[]);
char* read_password(const char* conf_dir);
int main(int argc, char* argv[]) {
if (argc < 2) {
fprintf(stderr, "error: missing command argument\n");
return EXIT_FAILURE;
}
srand((unsigned int)time(NULL));
const char* port = getenv("RCON_PORT");
if (port == NULL) {
fprintf(stderr, "error: missing $RCON_PORT env\n");
return EXIT_FAILURE;
}
const char* conf_dir = getenv("CONFIG");
if (conf_dir == NULL) {
fprintf(stderr, "error: missing $CONFIG env");
exit(EXIT_FAILURE);
}
int rcon_socket = rcon_open(port);
if (rcon_socket == -1) {
fprintf(stderr, "error: could not connect\n");
return EXIT_FAILURE;
}
if (!rcon_auth(rcon_socket, read_password(conf_dir))) {
fprintf(stderr, "error: login failed\n");
return EXIT_FAILURE;
}
packet pkt;
rcon_create(&pkt, RCON_TYPE_EXECCOMMAND, combine_args(argc, argv));
if (!rcon_send(rcon_socket, &pkt)) {
fprintf(stderr, "error: send command failed\n");
return EXIT_FAILURE;
}
if (rcon_recv(rcon_socket, &pkt, RCON_TYPE_RESPONSE) && pkt.length > 0) {
puts(pkt.body);
}
return EXIT_SUCCESS;
}
char* combine_args(int argc, char* argv[]) {
// combine all cli arguments
char* command = malloc(MAX_BODY);
memset(command, 0, MAX_BODY);
strcat(command, argv[1]);
for (int idx = 2; idx < argc; idx++) {
strcat(command, " ");
strcat(command, argv[idx]);
}
return command;
}
char* read_password(const char* conf_dir) {
char* path = malloc(strlen(conf_dir) + 64);
strcpy(path, conf_dir);
strcat(path, "/rconpw");
FILE* fptr = fopen(path, "r");
fseek(fptr, 0, SEEK_END);
long fsize = ftell(fptr);
fseek(fptr, 0, SEEK_SET); /* same as rewind(f); */
char *password = malloc(fsize + 1);
fread(password, fsize, 1, fptr);
fclose(fptr);
password[fsize] = 0;
if (password[fsize-1] == '\n') {
password[fsize-1] = 0;
}
return password;
}
int rcon_open(const char *port) {
struct sockaddr_in address = {
.sin_family = AF_INET,
.sin_port = htons(atoi(port))
};
inet_aton(RCON_HOST, &address.sin_addr);
int rcon_socket = socket(AF_INET, SOCK_STREAM, 0);
if (connect(rcon_socket, (struct sockaddr*) &address, sizeof(address)) < 0) {
return -1;
} else {
return rcon_socket;
}
}
void rcon_create(packet* pkt, packet_type type, const char* body) {
size_t body_length = strlen(body);
if (body_length >= MAX_BODY - 2) {
fprintf(stderr, "error: command to long");
exit(EXIT_FAILURE);
}
pkt->id = abs(rand());
pkt->type = type;
pkt->length = (uint32_t)(sizeof(pkt->id) + sizeof(pkt->type) + body_length + 2);
memset(pkt->body, 0, MAX_BODY);
strncpy(pkt->body, body, MAX_BODY);
}
bool rcon_recv(int rcon_socket, packet* pkt, packet_type expected_type) {
memset(pkt, 0, sizeof(*pkt));
// Read response packet length
ssize_t expected_length_bytes = sizeof(pkt->length);
ssize_t rx_bytes = recv(rcon_socket, &(pkt->length), expected_length_bytes, 0);
if (rx_bytes == -1) {
perror("error: socket error");
return false;
} else if (rx_bytes == 0) {
fprintf(stderr, "error: no data recieved\n");
return false;
} else if (rx_bytes < expected_length_bytes || pkt->length < MIN_PACKET || pkt->length > MAX_PACKET) {
fprintf(stderr, "error: invalid data\n");
return false;
}
ssize_t received = 0;
while (received < pkt->length) {
rx_bytes = recv(rcon_socket, (char *)pkt + sizeof(pkt->length) + received, pkt->length - received, 0);
if (rx_bytes < 0) {
perror("error: socket error");
return false;
} else if (rx_bytes == 0) {
fprintf(stderr, "error: connection lost\n");
return false;
}
received += rx_bytes;
}
return pkt->type == expected_type;
}
bool rcon_send(int rcon_socket, const packet* pkt) {
size_t length = sizeof(pkt->length) + pkt->length;
char *ptr = (char*) pkt;
while (length > 0) {
ssize_t ret = send(rcon_socket, ptr, length, 0);
if (ret == -1) {
return false;
}
ptr += ret;
length -= ret;
}
return true;
}
bool rcon_auth(int rcon_socket, const char* password) {
packet pkt;
rcon_create(&pkt, RCON_TYPE_AUTH, password);
if (!rcon_send(rcon_socket, &pkt)) {
return false;
}
if (!rcon_recv(rcon_socket, &pkt, RCON_TYPE_AUTH_RESPONSE)) {
return false;
}
return true;
}

170
update.sh Executable file
View File

@ -0,0 +1,170 @@
#!/bin/bash
set -e
SEMVER_REGEX="^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
stable_online_version=$(curl 'https://factorio.com/api/latest-releases' | jq '.stable.headless' -r)
experimental_online_version=$(curl 'https://factorio.com/api/latest-releases' | jq '.experimental.headless' -r)
stable_sha256=$(curl "https://factorio.com/download/sha256sums/" | grep -E "(factorio_headless_x64_|factorio-headless_linux_)${stable_online_version}.tar.xz" | awk '{print $1}')
experimental_sha256=$(curl "https://factorio.com/download/sha256sums/" | grep -E "(factorio_headless_x64_|factorio-headless_linux_)${experimental_online_version}.tar.xz" | awk '{print $1}')
stable_current_version=$(jq 'with_entries(select(.value.tags | index("stable"))) | keys | .[0]' buildinfo.json -r)
latest_current_version=$(jq 'with_entries(select(.value.tags | index("latest"))) | keys | .[0]' buildinfo.json -r)
echo "stable_online_version=${stable_online_version} experimental_online_version=${experimental_online_version}"
echo "stable_current_version=${stable_current_version} latest_current_version=${latest_current_version}"
if [[ -z "${stable_online_version}" ]] || [[ -z "${experimental_online_version}" ]]; then
exit
fi
if [[ "${stable_current_version}" == "${stable_online_version}" ]] && [[ "${latest_current_version}" == "${experimental_online_version}" ]]; then
exit
fi
function get-semver(){
local ver=$1
local type=$2
if [[ "$ver" =~ $SEMVER_REGEX ]]; then
local major=${BASH_REMATCH[1]}
local minor=${BASH_REMATCH[2]}
local patch=${BASH_REMATCH[3]}
fi
case $type in
major)
echo "$major"
;;
minor)
echo "$minor"
;;
patch)
echo "$patch"
;;
esac
}
stableOnlineVersionMajor=$(get-semver "${stable_online_version}" major)
stableOnlineVersionMinor=$(get-semver "${stable_online_version}" minor)
experimentalOnlineVersionMajor=$(get-semver "${experimental_online_version}" major)
experimentalOnlineVersionMinor=$(get-semver "${experimental_online_version}" minor)
stableCurrentVersionMajor=$(get-semver "${stable_current_version}" major)
stableCurrentVersionMinor=$(get-semver "${stable_current_version}" minor)
latestCurrentVersionMajor=$(get-semver "${latest_current_version}" major)
latestCurrentVersionMinor=$(get-semver "${latest_current_version}" minor)
stableOnlineVersionShort=$stableOnlineVersionMajor.$stableOnlineVersionMinor
experimentalOnlineVersionShort=$experimentalOnlineVersionMajor.$experimentalOnlineVersionMinor
stableCurrentVersionShort=$stableCurrentVersionMajor.$stableCurrentVersionMinor
latestCurrentVersionShort=$latestCurrentVersionMajor.$latestCurrentVersionMinor
echo "stableOnlineVersionShort=${stableOnlineVersionShort} experimentalOnlineVersionShort=${experimentalOnlineVersionShort}"
echo "stableCurrentVersionShort=${stableCurrentVersionShort} latestCurrentVersionShort=${latestCurrentVersionShort}"
tmpfile=$(mktemp)
# Remove stable tag
cp buildinfo.json "$tmpfile"
jq --arg stable_current_version "$stable_current_version" 'with_entries(if .key == $stable_current_version then .value.tags |= . - ["stable"] else . end)' "$tmpfile" > buildinfo.json
rm -f -- "$tmpfile"
# Remove latest tag
cp buildinfo.json "$tmpfile"
jq --arg latest_current_version "$latest_current_version" 'with_entries(if .key == $latest_current_version then .value.tags |= . - ["latest"] else . end)' "$tmpfile" > buildinfo.json
rm -f -- "$tmpfile"
# Update tag by stable
cp buildinfo.json "$tmpfile"
if [[ "$stable_online_version" == "$stable_current_version" ]]; then
jq --arg stable_current_version "$stable_current_version" --arg stable_online_version "$stable_online_version" --arg sha256 "$stable_sha256" 'with_entries(if .key == $stable_current_version then .key |= $stable_online_version | .value.sha256 |= $sha256 | .value.tags |= . - [$stable_current_version] + [$stable_online_version, "stable"] else . end)' "$tmpfile" > buildinfo.json
else
jq --arg stable_current_version "$stable_current_version" --arg stable_online_version "$stable_online_version" --arg sha256 "$stable_sha256" --arg stableOnlineVersionShort "$stableOnlineVersionShort" --arg stableOnlineVersionMajor "$stableOnlineVersionMajor" 'with_entries(if .key == $stable_current_version then .value.tags |= . - ["latest","stable",$stableOnlineVersionMajor] else . end) | to_entries | . + [{ key: $stable_online_version, value: { sha256: $sha256, tags: ["latest","stable",("stable-" + $stable_online_version),$stableOnlineVersionMajor,$stableOnlineVersionShort,$stable_online_version]}}] | from_entries' "$tmpfile" > buildinfo.json
fi
rm -f -- "$tmpfile"
# Update tag by latest
cp buildinfo.json "$tmpfile"
if [[ $experimental_online_version != "$stable_online_version" ]]; then
if [[ $stableOnlineVersionShort == "$experimentalOnlineVersionShort" ]]; then
jq --arg experimental_online_version "$experimental_online_version" --arg stable_online_version "$stable_online_version" --arg sha256 "$experimental_sha256" 'with_entries(if .key == $stable_online_version then .value.tags |= . - ["latest"] else . end) | to_entries | . + [{ key: $experimental_online_version, value: { sha256: $sha256, tags: ["latest", $experimental_online_version]}}] | from_entries' "$tmpfile" > buildinfo.json
else
jq --arg experimental_online_version "$experimental_online_version" --arg stable_online_version "$stable_online_version" --arg sha256 "$experimental_sha256" --arg experimentalOnlineVersionShort "$experimentalOnlineVersionShort" --arg experimentalOnlineVersionMajor "$experimentalOnlineVersionMajor" 'with_entries(if .key == $stable_online_version then .value.tags |= . - ["latest"] else . end) | to_entries | . + [{ key: $experimental_online_version, value: { sha256: $sha256, tags: ["latest",$experimentalOnlineVersionMajor,$experimentalOnlineVersionShort,$experimental_online_version]}}] | from_entries' "$tmpfile" > buildinfo.json
fi
fi
rm -f -- "$tmpfile"
# Generate README tags with logical sorting and de-duplication
# First, collect all unique tags with their versions
declare -A tag_versions
while IFS= read -r version; do
while IFS= read -r tag; do
# If this tag is already seen, compare versions to keep the latest
if [[ -n "${tag_versions[$tag]}" ]]; then
# Compare version strings - keep the higher one
if [[ "$version" > "${tag_versions[$tag]}" ]]; then
tag_versions[$tag]="$version"
fi
else
tag_versions[$tag]="$version"
fi
done < <(jq -r ".\"$version\".tags[]" buildinfo.json)
done < <(jq -r 'keys[]' buildinfo.json | sort -V -r)
# Build the tags list for README
readme_tags=""
# First add the current latest and stable tags
latest_version=$(jq -r 'to_entries | map(select(.value.tags | contains(["latest"]))) | .[0].key' buildinfo.json)
stable_version=$(jq -r 'to_entries | map(select(.value.tags | index("stable"))) | .[0].key' buildinfo.json)
if [[ -n "$latest_version" ]]; then
latest_tags=$(jq -r ".\"$latest_version\".tags | map(select(. == \"latest\" or . == \"$latest_version\")) | join(\", \")" buildinfo.json | sed 's/"/`/g')
readme_tags="${readme_tags}\n* \`${latest_tags}\`"
fi
if [[ -n "$stable_version" ]] && [[ "$stable_version" != "$latest_version" ]]; then
stable_tags=$(jq -r ".\"$stable_version\".tags | sort | join(\", \")" buildinfo.json | sed 's/"/`/g')
readme_tags="${readme_tags}\n* \`${stable_tags}\`"
fi
# Add major.minor tags (e.g., 2.0, 1.1) - only the latest version for each
declare -A major_minor_seen
while IFS= read -r version; do
if [[ "$version" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
major="${BASH_REMATCH[1]}"
minor="${BASH_REMATCH[2]}"
major_minor="$major.$minor"
# Skip if this is the latest or stable version (already added above)
if [[ "$version" == "$latest_version" ]] || [[ "$version" == "$stable_version" ]]; then
continue
fi
# Only add if we haven't seen this major.minor yet
if [[ -z "${major_minor_seen[$major_minor]}" ]]; then
major_minor_seen[$major_minor]=1
tags=$(jq -r ".\"$version\".tags | join(\", \")" buildinfo.json | sed 's/"/`/g')
if [[ -n "$tags" ]]; then
readme_tags="${readme_tags}\n* \`${tags}\`"
fi
fi
fi
done < <(jq -r 'keys[]' buildinfo.json | sort -V -r)
readme_tags="${readme_tags}\n"
perl -i -0777 -pe "s/<!-- start autogeneration tags -->.+<!-- end autogeneration tags -->/<!-- start autogeneration tags -->$readme_tags<!-- end autogeneration tags -->/s" README.md
# Replace VERSION and SHA256 args in docker-compose.yaml with latest stable values.
docker_compose_path="docker/docker-compose.yml"
sov="VERSION=${stable_online_version}" yq -i '.services.factorio.build.args[0] = env(sov)' "$docker_compose_path"
sha="SHA256=${stable_sha256}" yq -i '.services.factorio.build.args[1] = env(sha)' "$docker_compose_path"
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add buildinfo.json
git add README.md
git add docker/docker-compose.yml
git commit -a -m "Auto Update Factorio to stable version: ${stable_online_version} experimental version: ${experimental_online_version}"
git tag -f latest
git push
git push origin --tags -f