mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2025-11-07 02:23:42 +08:00
Compare commits
77 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abd30b9d91 | ||
|
|
c86408cbd6 | ||
|
|
1f51974c48 | ||
|
|
29f4cde296 | ||
|
|
c4a0035062 | ||
|
|
6724ddbd7d | ||
|
|
8d8ed63122 | ||
|
|
6f4ea81907 | ||
|
|
6d162744ec | ||
|
|
145b4aab5b | ||
|
|
2e4eb56d0b | ||
|
|
39c019193e | ||
|
|
faec563b4a | ||
|
|
9840f8e07a | ||
|
|
3a5895fa0f | ||
|
|
1bac5c8a7f | ||
|
|
dd76c60e2a | ||
|
|
ac78cc7dc5 | ||
|
|
66ac2d2002 | ||
|
|
0bd099d704 | ||
|
|
d2dac3cfb4 | ||
|
|
e81dc0f31d | ||
|
|
5015597183 | ||
|
|
64e2af9fa2 | ||
|
|
debb4b69fc | ||
|
|
c6d3dda171 | ||
|
|
7c0693c2ff | ||
|
|
76355d4857 | ||
|
|
404aaadefc | ||
|
|
be027e10be | ||
|
|
1c8cad92f8 | ||
|
|
fabb8ea3b7 | ||
|
|
2ee4abca54 | ||
|
|
5896928030 | ||
|
|
8652544982 | ||
|
|
a70338ec3c | ||
|
|
a84878abfc | ||
|
|
8421a391b7 | ||
|
|
f9340ec3d6 | ||
|
|
0cca9c5f83 | ||
|
|
13d60b7f47 | ||
|
|
f74771a9cc | ||
|
|
f24ba41930 | ||
|
|
f412580a4a | ||
|
|
5cde1b4438 | ||
|
|
7cfb57b1bc | ||
|
|
a478b58f97 | ||
|
|
8297f4f880 | ||
|
|
4c67343d33 | ||
|
|
53cc6998f0 | ||
|
|
d857d71e0d | ||
|
|
003c2766ce | ||
|
|
78594098cc | ||
|
|
3c31bc91e4 | ||
|
|
72141bab7a | ||
|
|
bc52463aa4 | ||
|
|
9fa68908a9 | ||
|
|
740dbec1b1 | ||
|
|
440d203730 | ||
|
|
1a83c67e2c | ||
|
|
34a707a2a5 | ||
|
|
cabb2cdfc9 | ||
|
|
dc52ccf172 | ||
|
|
bdd7fec3c3 | ||
|
|
bd8b03d089 | ||
|
|
a10588b0ce | ||
|
|
3503b86e12 | ||
|
|
9e124980cd | ||
|
|
675aa5e122 | ||
|
|
2a62d4e938 | ||
|
|
9cbb51cc86 | ||
|
|
7790f81d15 | ||
|
|
fdbff4879b | ||
|
|
739e679a66 | ||
|
|
0dea507d85 | ||
|
|
4f524c47d8 | ||
|
|
0c74201eb4 |
@@ -6,7 +6,10 @@
|
||||
.gitmodules
|
||||
Dockerfile
|
||||
Dockerfile.archive
|
||||
compose.yml
|
||||
compose.yaml
|
||||
docker-compose.yml
|
||||
docker-compose.yaml
|
||||
|
||||
*.md
|
||||
|
||||
|
||||
64
.github/ISSUE_TEMPLATE/BUG_REPORT.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/BUG_REPORT.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
name: "\U0001F41E Bug Report"
|
||||
description: Create a report to help us improve the container
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please search to see if an issue already exists for the bug you encountered.
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: Machine specifications
|
||||
description: The processor and RAM amount in your machine.
|
||||
placeholder: e.g. Intel N5105 / 16 GB
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating system
|
||||
description: The Linux distribution and kernel version as shown by `uname -a`.
|
||||
placeholder: e.g. Ubuntu 24.04 / Kernel 6.8.0-22-generic
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: docker
|
||||
attributes:
|
||||
label: Docker version
|
||||
description: The Docker version as shown by `docker -v`.
|
||||
placeholder: e.g. Docker version 26.0.1, build d260a54
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of the problem.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: compose
|
||||
attributes:
|
||||
label: Docker compose
|
||||
description: The Docker compose file (or otherwise `run` command).
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: log
|
||||
attributes:
|
||||
label: Docker log
|
||||
description: The Docker logfile of the container.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshot
|
||||
attributes:
|
||||
label: Screenshots (optional)
|
||||
description: Screenshots of the problem.
|
||||
validations:
|
||||
required: false
|
||||
44
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml
vendored
Normal file
44
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: "\U0001F680 Feature request"
|
||||
description: Suggest an idea for improving the container
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing feature request for this?
|
||||
description: Please search to see if the feature request already exists.
|
||||
options:
|
||||
- label: I have searched the existing feature requests
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Is your proposal related to a problem?
|
||||
description: |
|
||||
Provide a clear and concise description of what the problem is.
|
||||
For example, "I'm always frustrated when..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Describe the solution you'd like.
|
||||
description: |
|
||||
Provide a clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Describe alternatives you've considered.
|
||||
description: |
|
||||
Let us know about other solutions you've tried or researched.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: |
|
||||
Is there anything else you can add about the proposal?
|
||||
You might want to link to related issues here, if you haven't already.
|
||||
26
.github/ISSUE_TEMPLATE/QUESTION.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/QUESTION.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: "? Question"
|
||||
description: General questions about the container
|
||||
title: "[Question]: "
|
||||
labels: ["question"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is your question not already answered in the FAQ?
|
||||
description: Please read the [FAQ](https://github.com/vdsm/virtual-dsm/blob/master/readme.md) carefully to avoid asking duplicate questions.
|
||||
options:
|
||||
- label: I made sure the question is not listed in the [FAQ](https://github.com/vdsm/virtual-dsm/blob/master/readme.md).
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is this a general question and not a technical issue?
|
||||
description: For technical issues you must use the [bug report](https://github.com/vdsm/virtual-dsm/issues/new?assignees=&labels=bug&projects=&template=BUG_REPORT.yml&title=%5BBug%5D%3A+) form instead. It contains all the right fields (system info, logfiles, etc.) we need in order to be able to help you.
|
||||
options:
|
||||
- label: I am sure my question is not about a technical issue.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: Question
|
||||
description: What's the question you have about the container?
|
||||
validations:
|
||||
required: true
|
||||
18
.github/workflows/build.yml
vendored
18
.github/workflows/build.yml
vendored
@@ -8,6 +8,10 @@ on:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- '**/*.yml'
|
||||
- '**/*.js'
|
||||
- '**/*.css'
|
||||
- '**/*.html'
|
||||
- 'web/**'
|
||||
- '.gitignore'
|
||||
- '.dockerignore'
|
||||
- '.github/**'
|
||||
@@ -74,7 +78,7 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
provenance: false
|
||||
platforms: linux/amd64,linux/arm64,linux/arm
|
||||
platforms: linux/amd64,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
annotations: ${{ steps.meta.outputs.annotations }}
|
||||
@@ -99,3 +103,15 @@ jobs:
|
||||
url: ${{ secrets.GITLAB_URL }}
|
||||
token: ${{ secrets.GITLAB_TOKEN }}
|
||||
username: ${{ secrets.GITLAB_USERNAME }}
|
||||
-
|
||||
name: Send mail
|
||||
uses: action-pack/send-mail@v1
|
||||
with:
|
||||
to: ${{secrets.MAILTO}}
|
||||
from: Github Actions <${{secrets.MAILTO}}>
|
||||
connection_url: ${{secrets.MAIL_CONNECTION}}
|
||||
subject: Build of ${{ github.event.repository.name }} v${{ steps.meta.outputs.version }} completed
|
||||
body: |
|
||||
The build job of ${{ github.event.repository.name }} v${{ steps.meta.outputs.version }} was completed successfully!
|
||||
|
||||
See https://github.com/${{ github.repository }}/actions for more information.
|
||||
|
||||
18
.github/workflows/check.yml
vendored
18
.github/workflows/check.yml
vendored
@@ -7,8 +7,18 @@ jobs:
|
||||
name: shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run ShellCheck
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
env:
|
||||
SHELLCHECK_OPTS: -x --source-path=src -e SC2001 -e SC2034 -e SC2064 -e SC2317 -e SC2153 -e SC2028
|
||||
env:
|
||||
SHELLCHECK_OPTS: -x --source-path=src -e SC2001 -e SC2034 -e SC2064 -e SC2317 -e SC2153 -e SC2028
|
||||
-
|
||||
name: Lint Dockerfile
|
||||
uses: hadolint/hadolint-action@v3.1.0
|
||||
with:
|
||||
dockerfile: Dockerfile
|
||||
ignore: DL3008,DL3003,DL3006
|
||||
failure-threshold: warning
|
||||
|
||||
2
.github/workflows/hub.yml
vendored
2
.github/workflows/hub.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
-
|
||||
name: Docker Hub Description
|
||||
uses: peter-evans/dockerhub-description@v3
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
1
.github/workflows/test.yml
vendored
1
.github/workflows/test.yml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**/*.sh'
|
||||
- 'Dockerfile'
|
||||
- '.github/workflows/test.yml'
|
||||
- '.github/workflows/check.yml'
|
||||
|
||||
|
||||
18
Dockerfile
18
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM qemux/qemu-host as builder
|
||||
FROM qemux/qemu-host:2.04 as builder
|
||||
|
||||
# FROM golang as builder
|
||||
# WORKDIR /
|
||||
@@ -14,9 +14,9 @@ ARG DEBCONF_NOWARNINGS "yes"
|
||||
ARG DEBIAN_FRONTEND "noninteractive"
|
||||
ARG DEBCONF_NONINTERACTIVE_SEEN "true"
|
||||
|
||||
RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi \
|
||||
&& apt-get update \
|
||||
&& apt-get --no-install-recommends -y install \
|
||||
RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi && \
|
||||
apt-get update && \
|
||||
apt-get --no-install-recommends -y install \
|
||||
jq \
|
||||
tini \
|
||||
curl \
|
||||
@@ -37,11 +37,11 @@ RUN if [ "$TARGETPLATFORM" != "linux/amd64" ]; then extra="qemu-user"; fi \
|
||||
ca-certificates \
|
||||
netcat-openbsd \
|
||||
qemu-system-x86 \
|
||||
"$extra" \
|
||||
&& apt-get clean \
|
||||
&& unlink /etc/nginx/sites-enabled/default \
|
||||
&& sed -i 's/^worker_processes.*/worker_processes 1;/' /etc/nginx/nginx.conf \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
"$extra" && \
|
||||
apt-get clean && \
|
||||
unlink /etc/nginx/sites-enabled/default && \
|
||||
sed -i 's/^worker_processes.*/worker_processes 1;/' /etc/nginx/nginx.conf && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY ./src /run/
|
||||
COPY ./web /var/www/
|
||||
|
||||
@@ -5,12 +5,8 @@ services:
|
||||
image: vdsm/virtual-dsm:latest
|
||||
environment:
|
||||
DISK_SIZE: "16G"
|
||||
RAM_SIZE: "1G"
|
||||
CPU_CORES: "1"
|
||||
devices:
|
||||
- /dev/kvm
|
||||
device_cgroup_rules:
|
||||
- 'c *:* rwm'
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
ports:
|
||||
277
readme.md
277
readme.md
@@ -1,6 +1,6 @@
|
||||
<h1 align="center">Virtual DSM<br />
|
||||
<div align="center">
|
||||
<img src="https://github.com/vdsm/virtual-dsm/raw/master/.github/screen.jpg" title="Screenshot" style="max-width:100%;" width="432" />
|
||||
<a href="https://github.com/vdsm/virtual-dsm"><img src="https://github.com/vdsm/virtual-dsm/raw/master/.github/screen.jpg" title="Screenshot" style="max-width:100%;" width="432" /></a>
|
||||
</div>
|
||||
<div align="center">
|
||||
|
||||
@@ -11,18 +11,17 @@
|
||||
|
||||
</div></h1>
|
||||
|
||||
Virtual DSM in a docker container.
|
||||
Virtual DSM in a Docker container.
|
||||
|
||||
## Features
|
||||
|
||||
- Multiple disks
|
||||
- KVM acceleration
|
||||
- GPU pass-through
|
||||
- Upgrades supported
|
||||
|
||||
## Usage
|
||||
|
||||
Via `docker-compose.yml`
|
||||
Via Docker Compose:
|
||||
|
||||
```yaml
|
||||
version: "3"
|
||||
@@ -44,198 +43,200 @@ services:
|
||||
stop_grace_period: 2m
|
||||
```
|
||||
|
||||
Via `docker run`
|
||||
Via Docker CLI:
|
||||
|
||||
```bash
|
||||
docker run -it --rm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 60 vdsm/virtual-dsm
|
||||
docker run -it --rm --name dsm -p 5000:5000 --device=/dev/kvm --cap-add NET_ADMIN --stop-timeout 120 vdsm/virtual-dsm
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
* ### How do I use it?
|
||||
* ### How do I use it?
|
||||
|
||||
Very simple! These are the steps:
|
||||
|
||||
- Start the container and get some coffee.
|
||||
Very simple! These are the steps:
|
||||
|
||||
- Start the container and connect to [port 5000](http://localhost:5000) using your web browser.
|
||||
|
||||
- Connect to [port 5000](http://localhost:5000) of the container in your web browser.
|
||||
- Wait until DSM is ready, choose an username and password, and you will be taken to the desktop.
|
||||
|
||||
Enjoy your brand new machine, and don't forget to star this repo!
|
||||
|
||||
- Wait until DSM is ready, choose an username and password, and you will be taken to the desktop.
|
||||
* ### How do I change the storage location?
|
||||
|
||||
- Enjoy your brand new machine, and don't forget to star this repo!
|
||||
To change the storage location, include the following bind mount in your compose file:
|
||||
|
||||
* ### How do I change the size of the disk?
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/dsm:/storage
|
||||
```
|
||||
|
||||
To expand the default size of 16 GB, locate the `DISK_SIZE` setting in your compose file and modify it to your preferred capacity:
|
||||
Replace the example path `/var/dsm` with the desired storage folder.
|
||||
|
||||
* ### How do I change the size of the disk?
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK_SIZE: "128G"
|
||||
```
|
||||
|
||||
This can also be used to resize the existing disk to a larger capacity without any data loss.
|
||||
To expand the default size of 16 GB, locate the `DISK_SIZE` setting in your compose file and modify it to your preferred capacity:
|
||||
|
||||
* ### How do I change the storage location?
|
||||
```yaml
|
||||
environment:
|
||||
DISK_SIZE: "128G"
|
||||
```
|
||||
|
||||
This can also be used to resize the existing disk to a larger capacity without any data loss.
|
||||
|
||||
To change the storage location, include the following bind mount in your compose file:
|
||||
* ### How do I create a growable disk?
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
- /var/dsm:/storage
|
||||
```
|
||||
By default, the entire capacity of the disk is reserved in advance.
|
||||
|
||||
Replace the example path `/var/dsm` with the desired storage folder.
|
||||
To create a growable disk that only allocates space that is actually used, add the following environment variable:
|
||||
|
||||
* ### How do I create a growable disk?
|
||||
```yaml
|
||||
environment:
|
||||
DISK_FMT: "qcow2"
|
||||
```
|
||||
|
||||
By default, the entire capacity of the disk is reserved in advance.
|
||||
|
||||
To create a growable disk that only allocates space that is actually used, add the following environment variable:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK_FMT: "qcow2"
|
||||
```
|
||||
|
||||
Please note that this may reduce the write performance of the disk.
|
||||
Please note that this may reduce the write performance of the disk.
|
||||
|
||||
* ### How do I add multiple disks?
|
||||
|
||||
To create additional disks, modify your compose file like this:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK2_SIZE: "32G"
|
||||
DISK3_SIZE: "64G"
|
||||
volumes:
|
||||
- /home/example:/storage2
|
||||
- /mnt/data/example:/storage3
|
||||
```
|
||||
To create additional disks, modify your compose file like this:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DISK2_SIZE: "32G"
|
||||
DISK3_SIZE: "64G"
|
||||
volumes:
|
||||
- /home/example:/storage2
|
||||
- /mnt/data/example:/storage3
|
||||
```
|
||||
|
||||
* ### How do I pass-through a disk?
|
||||
* ### How do I pass-through a disk?
|
||||
|
||||
It is possible to pass-through disk devices directly by adding them to your compose file in this way:
|
||||
It is possible to pass-through disk devices directly by adding them to your compose file in this way:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DEVICE2: "/dev/sda"
|
||||
DEVICE3: "/dev/sdb"
|
||||
devices:
|
||||
- /dev/sda
|
||||
- /dev/sdb
|
||||
```
|
||||
```yaml
|
||||
devices:
|
||||
- /dev/disk/by-uuid/12345-12345-12345-12345-12345:/disk2
|
||||
- /dev/disk/by-uuid/45678-45678-45678-45678-45678:/disk3
|
||||
```
|
||||
|
||||
Please note that the device needs to be totally empty (without any partition table) otherwise DSM does not always format it into a volume.
|
||||
Make sure to bind the disk via its UUID (obtainable via `lsblk -o name,uuid`) instead of its name (`/dev/sdc`), to prevent ever binding the wrong disk when the drive letters happen to change.
|
||||
|
||||
Do NOT use this feature with the goal of sharing files from the host, they will all be lost without warning when DSM creates the volume.
|
||||
Please note that the device needs to be totally empty (without any partition table) otherwise DSM does not always format it into a volume.
|
||||
|
||||
* ### How do I increase the amount of CPU or RAM?
|
||||
Do NOT use this feature with the goal of sharing files from the host, they will all be lost without warning when DSM creates the volume.
|
||||
|
||||
By default, a single CPU core and 1 GB of RAM are allocated to the container.
|
||||
* ### How do I increase the amount of CPU or RAM?
|
||||
|
||||
To increase this, add the following environment variables:
|
||||
By default, a single CPU core and 1 GB of RAM are allocated to the container.
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
RAM_SIZE: "4G"
|
||||
CPU_CORES: "4"
|
||||
```
|
||||
If there arises a need to increase this, add the following environment variables:
|
||||
|
||||
* ### How do I verify if my system supports KVM?
|
||||
```yaml
|
||||
environment:
|
||||
RAM_SIZE: "4G"
|
||||
CPU_CORES: "4"
|
||||
```
|
||||
|
||||
To verify if your system supports KVM, run the following commands:
|
||||
* ### How do I verify if my system supports KVM?
|
||||
|
||||
```bash
|
||||
sudo apt install cpu-checker
|
||||
sudo kvm-ok
|
||||
```
|
||||
To verify if your system supports KVM, run the following commands:
|
||||
|
||||
If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.
|
||||
```bash
|
||||
sudo apt install cpu-checker
|
||||
sudo kvm-ok
|
||||
```
|
||||
|
||||
* ### How do I assign an individual IP address to the container?
|
||||
If you receive an error from `kvm-ok` indicating that KVM acceleration can't be used, check the virtualization settings in the BIOS.
|
||||
|
||||
By default, the container uses bridge networking, which shares the IP address with the host.
|
||||
* ### How do I assign an individual IP address to the container?
|
||||
|
||||
If you want to assign an individual IP address to the container, you can create a macvlan network as follows:
|
||||
By default, the container uses bridge networking, which shares the IP address with the host.
|
||||
|
||||
```bash
|
||||
docker network create -d macvlan \
|
||||
--subnet=192.168.0.0/24 \
|
||||
--gateway=192.168.0.1 \
|
||||
--ip-range=192.168.0.100/28 \
|
||||
-o parent=eth0 vdsm
|
||||
```
|
||||
|
||||
Be sure to modify these values to match your local subnet.
|
||||
If you want to assign an individual IP address to the container, you can create a macvlan network as follows:
|
||||
|
||||
Once you have created the network, change your compose file to look as follows:
|
||||
```bash
|
||||
docker network create -d macvlan \
|
||||
--subnet=192.168.0.0/24 \
|
||||
--gateway=192.168.0.1 \
|
||||
--ip-range=192.168.0.100/28 \
|
||||
-o parent=eth0 vdsm
|
||||
```
|
||||
|
||||
Be sure to modify these values to match your local subnet.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
dsm:
|
||||
container_name: dsm
|
||||
..<snip>..
|
||||
networks:
|
||||
vdsm:
|
||||
ipv4_address: 192.168.0.100
|
||||
Once you have created the network, change your compose file to look as follows:
|
||||
|
||||
networks:
|
||||
vdsm:
|
||||
external: true
|
||||
```
|
||||
|
||||
An added benefit of this approach is that you won't have to perform any port mapping anymore, since all ports will be exposed by default.
|
||||
```yaml
|
||||
services:
|
||||
dsm:
|
||||
container_name: dsm
|
||||
..<snip>..
|
||||
networks:
|
||||
vdsm:
|
||||
ipv4_address: 192.168.0.100
|
||||
|
||||
Please note that this IP address won't be accessible from the Docker host due to the design of macvlan, which doesn't permit communication between the two. If this is a concern, you need to create a [second macvlan](https://blog.oddbit.com/post/2018-03-12-using-docker-macvlan-networks/#host-access) as a workaround.
|
||||
networks:
|
||||
vdsm:
|
||||
external: true
|
||||
```
|
||||
|
||||
An added benefit of this approach is that you won't have to perform any port mapping anymore, since all ports will be exposed by default.
|
||||
|
||||
* ### How can DSM acquire an IP address from my router?
|
||||
Please note that this IP address won't be accessible from the Docker host due to the design of macvlan, which doesn't permit communication between the two. If this is a concern, you need to create a [second macvlan](https://blog.oddbit.com/post/2018-03-12-using-docker-macvlan-networks/#host-access) as a workaround.
|
||||
|
||||
After configuring the container for macvlan (see above), it is possible for DSM to become part of your home network by requesting an IP from your router, just like your other devices.
|
||||
* ### How can DSM acquire an IP address from my router?
|
||||
|
||||
To enable this feature, add the following lines to your compose file:
|
||||
After configuring the container for macvlan (see above), it is possible for DSM to become part of your home network by requesting an IP from your router, just like your other devices.
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
DHCP: "Y"
|
||||
device_cgroup_rules:
|
||||
- 'c *:* rwm'
|
||||
```
|
||||
To enable this mode, add the following lines to your compose file:
|
||||
|
||||
Please note that even if you don't want DHCP, it's still recommended to enable this feature, as it prevents NAT issues and increases performance by using a `macvtap` interface. In that case, just set a static IP from the DSM control panel after you enabled this mode.
|
||||
```yaml
|
||||
environment:
|
||||
DHCP: "Y"
|
||||
devices:
|
||||
- /dev/vhost-net
|
||||
device_cgroup_rules:
|
||||
- 'c *:* rwm'
|
||||
```
|
||||
|
||||
* ### How do I pass-through the GPU?
|
||||
Please note that even if you don't need DHCP, it's still recommended to enable this mode, as it prevents NAT issues and increases performance by using a `macvtap` interface. You can just set a static IP from the DSM control panel afterwards.
|
||||
|
||||
To pass-through your Intel GPU, add the following lines to your compose file:
|
||||
* ### How do I pass-through the GPU?
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
GPU: "Y"
|
||||
devices:
|
||||
- /dev/dri
|
||||
```
|
||||
To pass-through your Intel GPU, add the following lines to your compose file:
|
||||
|
||||
This can be used to enable the facial recognition function in Synology Photos for example.
|
||||
```yaml
|
||||
environment:
|
||||
GPU: "Y"
|
||||
devices:
|
||||
- /dev/dri
|
||||
```
|
||||
|
||||
* ### How do I install a specific version of vDSM?
|
||||
This can be used to enable the facial recognition function in Synology Photos for example.
|
||||
|
||||
By default, version 7.2 will be installed, but if you prefer an older version, you can add its download URL to your compose file as follows:
|
||||
* ### How do I install a specific version of vDSM?
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
URL: "https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
||||
```
|
||||
By default, version 7.2 will be installed, but if you prefer an older version, you can add its download URL to your compose file as follows:
|
||||
|
||||
With this method, it is even possible to switch between different versions while keeping all your file data intact.
|
||||
```yaml
|
||||
environment:
|
||||
URL: "https://global.synologydownload.com/download/DSM/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
||||
```
|
||||
|
||||
* ### What are the differences compared to the standard DSM?
|
||||
With this method, it is even possible to switch between different versions while keeping all your file data intact.
|
||||
|
||||
There are only two minor differences: the Virtual Machine Manager package is not available, and Surveillance Station will not include any free licenses.
|
||||
|
||||
* ### Is this project legal?
|
||||
* ### What are the differences compared to the standard DSM?
|
||||
|
||||
Yes, this project contains only open-source code and does not distribute any copyrighted material. Neither does it try to circumvent any copyright protection measures. So under all applicable laws, this project would be considered legal.
|
||||
|
||||
However, by installing Synology's Virtual DSM, you must accept their end-user license agreement, which does not permit installation on non-Synology hardware. So only run this project on an official Synology NAS, as any other use will be a violation of their terms and conditions.
|
||||
There are only two minor differences: the Virtual Machine Manager package is not available, and Surveillance Station will not include any free licenses.
|
||||
|
||||
* ### Is this project legal?
|
||||
|
||||
Yes, this project contains only open-source code and does not distribute any copyrighted material. Neither does it try to circumvent any copyright protection measures. So under all applicable laws, this project would be considered legal.
|
||||
|
||||
However, by installing Synology's Virtual DSM, you must accept their end-user license agreement, which does not permit installation on non-Synology hardware. So only run this container on an official Synology NAS, as any other use will be a violation of their terms and conditions.
|
||||
|
||||
## Stars
|
||||
[](https://starchart.cc/vdsm/virtual-dsm)
|
||||
|
||||
## Disclaimer
|
||||
|
||||
@@ -247,5 +248,5 @@ Only run this container on Synology hardware, any other use is not permitted by
|
||||
|
||||
[Build]: https://github.com/vdsm/virtual-dsm/actions/workflows/build.yml/badge.svg
|
||||
[Size]: https://img.shields.io/docker/image-size/vdsm/virtual-dsm/latest?color=066da5&label=size
|
||||
[Pulls]: https://img.shields.io/docker/pulls/kroese/virtual-dsm.svg?style=flat&label=pulls&logo=docker
|
||||
[Pulls]: https://img.shields.io/docker/pulls/vdsm/virtual-dsm.svg?style=flat&label=pulls&logo=docker
|
||||
[Version]: https://img.shields.io/docker/v/vdsm/virtual-dsm/latest?arch=amd64&sort=semver&color=066da5
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${NETWORK:="Y"}"
|
||||
|
||||
[ -f "/run/shm/qemu.end" ] && echo "QEMU is shutting down.." && exit 1
|
||||
[ ! -f "/run/shm/qemu.pid" ] && echo "QEMU is not running yet.." && exit 0
|
||||
[ ! -s "/run/shm/qemu.pid" ] && echo "QEMU is not running yet.." && exit 0
|
||||
[[ "$NETWORK" != [Yy1]* ]] && echo "Networking is disabled.." && exit 0
|
||||
|
||||
file="/run/shm/dsm.url"
|
||||
address="/run/shm/qemu.ip"
|
||||
|
||||
[ ! -f "$file" ] && echo "DSM has not enabled networking yet.." && exit 1
|
||||
[ ! -s "$file" ] && echo "DSM has not enabled networking yet.." && exit 1
|
||||
|
||||
location=$(<"$file")
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
DEF_OPTS="-nodefaults -boot strict=on"
|
||||
RAM_OPTS=$(echo "-m $RAM_SIZE" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||
CPU_OPTS="-cpu $CPU_MODEL -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
|
||||
MAC_OPTS="-machine type=q35,usb=off,dump-guest-core=off,hpet=off${KVM_OPTS}"
|
||||
RAM_OPTS=$(echo "-m ${RAM_SIZE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||
CPU_OPTS="-cpu $CPU_FLAGS -smp $CPU_CORES,sockets=1,dies=1,cores=$CPU_CORES,threads=1"
|
||||
MAC_OPTS="-machine type=q35,usb=off,vmport=off,dump-guest-core=off,hpet=off${KVM_OPTS}"
|
||||
DEV_OPTS="-device virtio-balloon-pci,id=balloon0,bus=pcie.0,addr=0x4"
|
||||
DEV_OPTS="$DEV_OPTS -object rng-random,id=objrng0,filename=/dev/urandom"
|
||||
DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0x1c"
|
||||
@@ -12,4 +12,18 @@ DEV_OPTS="$DEV_OPTS -device virtio-rng-pci,rng=objrng0,id=rng0,bus=pcie.0,addr=0
|
||||
ARGS="$DEF_OPTS $CPU_OPTS $RAM_OPTS $MAC_OPTS $DISPLAY_OPTS $MON_OPTS $SERIAL_OPTS $NET_OPTS $DISK_OPTS $DEV_OPTS $ARGUMENTS"
|
||||
ARGS=$(echo "$ARGS" | sed 's/\t/ /g' | tr -s ' ')
|
||||
|
||||
# Check available memory as the very last step
|
||||
|
||||
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
|
||||
AVAIL_GB=$(( (RAM_AVAIL + 1073741823)/1073741824 ))
|
||||
|
||||
if (( (RAM_WANTED + 500000000) > RAM_AVAIL )); then
|
||||
error "Your configured RAM_SIZE of $WANTED_GB GB is higher than the $AVAIL_GB GB of memory available, please set a lower value."
|
||||
exit 17
|
||||
fi
|
||||
|
||||
if (( (RAM_WANTED + 1450000000) > RAM_AVAIL )); then
|
||||
warn "your configured RAM_SIZE of $WANTED_GB GB is much too close to the $AVAIL_GB GB of memory available, please set a lower value."
|
||||
fi
|
||||
|
||||
return 0
|
||||
|
||||
132
src/disk.sh
132
src/disk.sh
@@ -13,8 +13,8 @@ set -Eeuo pipefail
|
||||
BOOT="$STORAGE/$BASE.boot.img"
|
||||
SYSTEM="$STORAGE/$BASE.system.img"
|
||||
|
||||
[ ! -f "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81
|
||||
[ ! -f "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82
|
||||
[ ! -s "$BOOT" ] && error "Virtual DSM boot-image does not exist ($BOOT)" && exit 81
|
||||
[ ! -s "$SYSTEM" ] && error "Virtual DSM system-image does not exist ($SYSTEM)" && exit 82
|
||||
|
||||
DISK_OPTS="\
|
||||
-object iothread,id=io2 \
|
||||
@@ -80,13 +80,23 @@ getSize() {
|
||||
isCow() {
|
||||
local FS=$1
|
||||
|
||||
if [[ "${FS,,}" == "xfs" || "${FS,,}" == "zfs" || "${FS,,}" == "btrfs" || "${FS,,}" == "bcachefs" ]]; then
|
||||
if [[ "${FS,,}" == "btrfs" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
supportsDirect() {
|
||||
local FS=$1
|
||||
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
createDisk() {
|
||||
local DISK_FILE=$1
|
||||
local DISK_SPACE=$2
|
||||
@@ -112,8 +122,8 @@ createDisk() {
|
||||
fi
|
||||
fi
|
||||
|
||||
MSG="Creating a $DISK_TYPE $DISK_DESC image in $DISK_FMT format with a size of $DISK_SPACE..."
|
||||
info "$MSG" && html "$MSG"
|
||||
html "Creating a $DISK_DESC image..."
|
||||
info "Creating a $DISK_SPACE $DISK_TYPE $DISK_DESC image in $DISK_FMT format..."
|
||||
|
||||
local FAIL="Could not create a $DISK_TYPE $DISK_FMT $DISK_DESC image of $DISK_SPACE ($DISK_FILE)"
|
||||
|
||||
@@ -266,8 +276,8 @@ convertDisk() {
|
||||
fi
|
||||
fi
|
||||
|
||||
MSG="Converting $DISK_DESC to $DST_FMT, please wait until completed..."
|
||||
info "$MSG" && html "$MSG"
|
||||
html "Converting $DISK_DESC to $DST_FMT..."
|
||||
info "Converting $DISK_DESC to $DST_FMT, please wait until completed..."
|
||||
|
||||
local CONV_FLAGS="-p"
|
||||
local DISK_PARAM="$DISK_ALLOC"
|
||||
@@ -306,8 +316,8 @@ convertDisk() {
|
||||
fi
|
||||
fi
|
||||
|
||||
MSG="Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
|
||||
info "$MSG" && html "$MSG"
|
||||
html "Conversion of $DISK_DESC completed..."
|
||||
info "Conversion of $DISK_DESC to $DST_FMT completed succesfully!"
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -329,6 +339,10 @@ checkFS () {
|
||||
info "Warning: the filesystem of $DIR is FUSE, this extra layer will negatively affect performance!"
|
||||
fi
|
||||
|
||||
if ! supportsDirect "$FS"; then
|
||||
info "Warning: the filesystem of $DIR is $FS, which does not support O_DIRECT mode, adjusting settings..."
|
||||
fi
|
||||
|
||||
if isCow "$FS"; then
|
||||
if [ -f "$DISK_FILE" ]; then
|
||||
FA=$(lsattr "$DISK_FILE")
|
||||
@@ -341,17 +355,39 @@ checkFS () {
|
||||
return 0
|
||||
}
|
||||
|
||||
addDisk () {
|
||||
createDevice () {
|
||||
|
||||
local DISK_ID=$1
|
||||
local DISK_BASE=$2
|
||||
local DISK_EXT=$3
|
||||
local DISK_DESC=$4
|
||||
local DISK_SPACE=$5
|
||||
local DISK_INDEX=$6
|
||||
local DISK_ADDRESS=$7
|
||||
local DISK_FMT=$8
|
||||
local DISK_FILE=$2
|
||||
local DISK_INDEX=$3
|
||||
local DISK_ADDRESS=$4
|
||||
local DISK_FMT=$5
|
||||
local DISK_IO=$6
|
||||
local DISK_CACHE=$7
|
||||
|
||||
local result="-drive file=$DISK_FILE,if=none,id=drive-$DISK_ID,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on"
|
||||
|
||||
result="$result \
|
||||
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
|
||||
-device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
|
||||
|
||||
echo "$result"
|
||||
return 0
|
||||
}
|
||||
|
||||
addDisk () {
|
||||
local DISK_BASE=$1
|
||||
local DISK_EXT=$2
|
||||
local DISK_DESC=$3
|
||||
local DISK_SPACE=$4
|
||||
local DISK_INDEX=$5
|
||||
local DISK_ADDRESS=$6
|
||||
local DISK_FMT=$7
|
||||
local DISK_IO=$8
|
||||
local DISK_CACHE=$9
|
||||
local DISK_ID="userdata$DISK_INDEX"
|
||||
local DISK_FILE="$DISK_BASE.$DISK_EXT"
|
||||
local DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE
|
||||
local DIR DATA_SIZE FS PREV_FMT PREV_EXT CUR_SIZE OPTS
|
||||
|
||||
DIR=$(dirname "$DISK_FILE")
|
||||
[ ! -d "$DIR" ] && return 0
|
||||
@@ -371,7 +407,12 @@ addDisk () {
|
||||
FS=$(stat -f -c %T "$DIR")
|
||||
checkFS "$FS" "$DISK_FILE" "$DISK_DESC" || exit $?
|
||||
|
||||
if ! [ -f "$DISK_FILE" ] ; then
|
||||
if ! supportsDirect "$FS"; then
|
||||
DISK_IO="threads"
|
||||
DISK_CACHE="writeback"
|
||||
fi
|
||||
|
||||
if ! [ -s "$DISK_FILE" ] ; then
|
||||
|
||||
if [[ "${DISK_FMT,,}" != "raw" ]]; then
|
||||
PREV_FMT="raw"
|
||||
@@ -380,12 +421,12 @@ addDisk () {
|
||||
fi
|
||||
PREV_EXT=$(fmt2ext "$PREV_FMT")
|
||||
|
||||
if [ -f "$DISK_BASE.$PREV_EXT" ] ; then
|
||||
if [ -s "$DISK_BASE.$PREV_EXT" ] ; then
|
||||
convertDisk "$DISK_BASE.$PREV_EXT" "$PREV_FMT" "$DISK_FILE" "$DISK_FMT" "$DISK_BASE" "$DISK_DESC" "$FS" || exit $?
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$DISK_FILE" ]; then
|
||||
if [ -s "$DISK_FILE" ]; then
|
||||
|
||||
CUR_SIZE=$(getSize "$DISK_FILE")
|
||||
|
||||
@@ -399,29 +440,26 @@ addDisk () {
|
||||
|
||||
fi
|
||||
|
||||
DISK_OPTS="$DISK_OPTS \
|
||||
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
|
||||
-drive file=$DISK_FILE,if=none,id=drive-$DISK_ID,format=$DISK_FMT,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
|
||||
-device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
|
||||
OPTS=$(createDevice "$DISK_ID" "$DISK_FILE" "$DISK_INDEX" "$DISK_ADDRESS" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE")
|
||||
DISK_OPTS="$DISK_OPTS $OPTS"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
addDevice () {
|
||||
|
||||
local DISK_ID=$1
|
||||
local DISK_DEV=$2
|
||||
local DISK_DESC=$3
|
||||
local DISK_INDEX=$4
|
||||
local DISK_ADDRESS=$5
|
||||
local DISK_DEV=$1
|
||||
local DISK_DESC=$2
|
||||
local DISK_INDEX=$3
|
||||
local DISK_ADDRESS=$4
|
||||
local DISK_ID="userdata$DISK_INDEX"
|
||||
|
||||
[ -z "$DISK_DEV" ] && return 0
|
||||
[ ! -b "$DISK_DEV" ] && error "Device $DISK_DEV cannot be found! Please add it to the 'devices' section of your compose file." && exit 55
|
||||
|
||||
DISK_OPTS="$DISK_OPTS \
|
||||
-device virtio-scsi-pci,id=hw-$DISK_ID,iothread=io2,bus=pcie.0,addr=$DISK_ADDRESS \
|
||||
-drive file=$DISK_DEV,if=none,id=drive-$DISK_ID,format=raw,cache=$DISK_CACHE,aio=$DISK_IO,discard=$DISK_DISCARD,detect-zeroes=on \
|
||||
-device scsi-hd,bus=hw-$DISK_ID.0,channel=0,scsi-id=0,lun=0,drive=drive-$DISK_ID,id=$DISK_ID,rotation_rate=$DISK_ROTATION,bootindex=$DISK_INDEX"
|
||||
local OPTS
|
||||
OPTS=$(createDevice "$DISK_ID" "$DISK_DEV" "$DISK_INDEX" "$DISK_ADDRESS" "raw" "$DISK_IO" "$DISK_CACHE")
|
||||
DISK_OPTS="$DISK_OPTS $OPTS"
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -489,28 +527,38 @@ DISK4_FILE="/storage4/data4"
|
||||
: "${DEVICE3:=""}"
|
||||
: "${DEVICE4:=""}"
|
||||
|
||||
[ -z "$DEVICE" ] && [ -b "/disk1" ] && DEVICE="/disk1"
|
||||
[ -z "$DEVICE2" ] && [ -b "/disk2" ] && DEVICE2="/disk2"
|
||||
[ -z "$DEVICE3" ] && [ -b "/disk3" ] && DEVICE3="/disk3"
|
||||
[ -z "$DEVICE4" ] && [ -b "/disk4" ] && DEVICE4="/disk4"
|
||||
|
||||
[ -z "$DEVICE" ] && [ -b "/dev/disk1" ] && DEVICE="/dev/disk1"
|
||||
[ -z "$DEVICE2" ] && [ -b "/dev/disk2" ] && DEVICE2="/dev/disk2"
|
||||
[ -z "$DEVICE3" ] && [ -b "/dev/disk3" ] && DEVICE3="/dev/disk3"
|
||||
[ -z "$DEVICE4" ] && [ -b "/dev/disk4" ] && DEVICE4="/dev/disk4"
|
||||
|
||||
if [ -n "$DEVICE" ]; then
|
||||
addDevice "userdata" "$DEVICE" "device" "3" "0xc" || exit $?
|
||||
addDevice "$DEVICE" "device" "3" "0xc" || exit $?
|
||||
else
|
||||
addDisk "userdata" "$DISK1_FILE" "$DISK_EXT" "disk" "$DISK_SIZE" "3" "0xc" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK1_FILE" "$DISK_EXT" "disk" "$DISK_SIZE" "3" "0xc" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE2" ]; then
|
||||
addDevice "userdata2" "$DEVICE2" "device2" "4" "0xd" || exit $?
|
||||
addDevice "$DEVICE2" "device2" "4" "0xd" || exit $?
|
||||
else
|
||||
addDisk "userdata2" "$DISK2_FILE" "$DISK_EXT" "disk2" "$DISK2_SIZE" "4" "0xd" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK2_FILE" "$DISK_EXT" "disk2" "$DISK2_SIZE" "4" "0xd" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE3" ]; then
|
||||
addDevice "userdata3" "$DEVICE3" "device3" "5" "0xe" || exit $?
|
||||
addDevice "$DEVICE3" "device3" "5" "0xe" || exit $?
|
||||
else
|
||||
addDisk "userdata3" "$DISK3_FILE" "$DISK_EXT" "disk3" "$DISK3_SIZE" "5" "0xe" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK3_FILE" "$DISK_EXT" "disk3" "$DISK3_SIZE" "5" "0xe" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
if [ -n "$DEVICE4" ]; then
|
||||
addDevice "userdata4" "$DEVICE4" "device4" "6" "0xf" || exit $?
|
||||
addDevice "$DEVICE4" "device4" "6" "0xf" || exit $?
|
||||
else
|
||||
addDisk "userdata4" "$DISK4_FILE" "$DISK_EXT" "disk4" "$DISK4_SIZE" "6" "0xf" "$DISK_FMT" || exit $?
|
||||
addDisk "$DISK4_FILE" "$DISK_EXT" "disk4" "$DISK4_SIZE" "6" "0xf" "$DISK_FMT" "$DISK_IO" "$DISK_CACHE" || exit $?
|
||||
fi
|
||||
|
||||
html "Initialized disks successfully..."
|
||||
|
||||
@@ -15,7 +15,8 @@ if [[ "$GPU" != [Yy1]* ]] || [[ "$ARCH" != "amd64" ]]; then
|
||||
|
||||
fi
|
||||
|
||||
DISPLAY_OPTS="-display egl-headless,rendernode=/dev/dri/renderD128 -vga $VGA"
|
||||
DISPLAY_OPTS="-display egl-headless,rendernode=/dev/dri/renderD128"
|
||||
DISPLAY_OPTS="$DISPLAY_OPTS -vga $VGA"
|
||||
|
||||
[ ! -d /dev/dri ] && mkdir -m 755 /dev/dri
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@ cd /run
|
||||
|
||||
trap - ERR
|
||||
|
||||
info "Booting ${APP}..."
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo "Arguments: $ARGS" && echo
|
||||
|
||||
if [[ "$CONSOLE" == [Yy]* ]]; then
|
||||
exec qemu-system-x86_64 ${ARGS:+ $ARGS}
|
||||
fi
|
||||
|
||||
[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && echo "Arguments: $ARGS" && echo
|
||||
{ qemu-system-x86_64 ${ARGS:+ $ARGS} >"$QEMU_OUT" 2>"$QEMU_LOG"; rc=$?; } || :
|
||||
(( rc != 0 )) && error "$(<"$QEMU_LOG")" && exit 15
|
||||
|
||||
@@ -30,4 +32,5 @@ terminal
|
||||
tail -fn +0 "$QEMU_LOG" 2>/dev/null &
|
||||
cat "$QEMU_TERM" 2>/dev/null & wait $! || :
|
||||
|
||||
sleep 1 && finish 0
|
||||
sleep 1 & wait $!
|
||||
finish 0
|
||||
|
||||
@@ -5,6 +5,7 @@ set -Eeuo pipefail
|
||||
|
||||
if [ -f "$STORAGE/dsm.ver" ]; then
|
||||
BASE=$(<"$STORAGE/dsm.ver")
|
||||
[ -z "$BASE" ] && BASE="DSM_VirtualDSM_69057"
|
||||
else
|
||||
# Fallback for old installs
|
||||
BASE="DSM_VirtualDSM_42962"
|
||||
@@ -12,14 +13,14 @@ fi
|
||||
|
||||
if [ -n "$URL" ]; then
|
||||
BASE=$(basename "$URL" .pat)
|
||||
if [ ! -f "$STORAGE/$BASE.system.img" ]; then
|
||||
if [ ! -s "$STORAGE/$BASE.system.img" ]; then
|
||||
BASE=$(basename "${URL%%\?*}" .pat)
|
||||
: "${BASE//+/ }"; printf -v BASE '%b' "${_//%/\\x}"
|
||||
BASE=$(echo "$BASE" | sed -e 's/[^A-Za-z0-9._-]/_/g')
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -f "$STORAGE/$BASE.boot.img" ]] && [[ -f "$STORAGE/$BASE.system.img" ]]; then
|
||||
if [[ -s "$STORAGE/$BASE.boot.img" ]] && [[ -s "$STORAGE/$BASE.system.img" ]]; then
|
||||
return 0 # Previous installation found
|
||||
fi
|
||||
|
||||
@@ -65,7 +66,15 @@ if [[ "${FS,,}" == "fuse"* ]]; then
|
||||
info "Warning: the filesystem of $STORAGE is FUSE, this extra layer will negatively affect performance!"
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" != "fat"* && "${FS,,}" != "vfat"* && "${FS,,}" != "exfat"* && "${FS,,}" != "ntfs"* && "${FS,,}" != "msdos"* ]]; then
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
info "Warning: the filesystem of $STORAGE is $FS, which does not support O_DIRECT mode, adjusting settings..."
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" == "fat"* || "${FS,,}" == "vfat"* || "${FS,,}" == "msdos"* ]]; then
|
||||
error "Unable to install on $FS filesystems, please use a different filesystem for /storage." && exit 61
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" != "exfat"* && "${FS,,}" != "ntfs"* && "${FS,,}" != "unknown"* ]]; then
|
||||
TMP="$STORAGE/tmp"
|
||||
else
|
||||
TMP="/tmp/dsm"
|
||||
@@ -102,29 +111,48 @@ fi
|
||||
ROOT="Y"
|
||||
RDC="$STORAGE/dsm.rd"
|
||||
|
||||
if [ ! -f "$RDC" ]; then
|
||||
if [ ! -s "$RDC" ]; then
|
||||
|
||||
MSG="Downloading installer..."
|
||||
PRG="Downloading installer ([P])..."
|
||||
info "Install: $MSG" && html "$MSG"
|
||||
|
||||
RD="$TMP/rd.gz"
|
||||
SIZE=5394188
|
||||
POS="65627648-71021835"
|
||||
VERIFY="b4215a4b213ff5154db0488f92c87864"
|
||||
LOC="$DL/release/7.0.1/42218/DSM_VirtualDSM_42218.pat"
|
||||
|
||||
{ curl -r "$POS" -sfk -S -o "$RD" "$LOC"; rc=$?; } || :
|
||||
(( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60
|
||||
rm -f "$RD"
|
||||
rm -f "$RDC"
|
||||
/run/progress.sh "$RD" "$SIZE" "$PRG" &
|
||||
{ curl -r "$POS" -sfk --connect-timeout 10 -S -o "$RD" "$LOC"; rc=$?; } || :
|
||||
|
||||
SUM=$(md5sum "$RD" | cut -f 1 -d " ")
|
||||
fKill "progress.sh"
|
||||
|
||||
if (( rc != 0 )); then
|
||||
if (( rc != 22 )) && (( rc != 56 )); then
|
||||
error "Failed to download $LOC, reason: $rc" && exit 60
|
||||
fi
|
||||
SUM="skip"
|
||||
else
|
||||
SUM=$(md5sum "$RD" | cut -f 1 -d " ")
|
||||
fi
|
||||
|
||||
if [ "$SUM" != "$VERIFY" ]; then
|
||||
|
||||
PAT="/install.pat"
|
||||
rm "$RD"
|
||||
SIZE=379637760
|
||||
|
||||
rm -f "$RD"
|
||||
rm -f "$PAT"
|
||||
|
||||
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
(( rc != 0 )) && error "Failed to download $LOC, reason: $rc" && exit 60
|
||||
html "$MSG"
|
||||
/run/progress.sh "$PAT" "$SIZE" "$PRG" &
|
||||
{ wget "$LOC" -O "$PAT" -q --no-check-certificate --timeout=10 --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
|
||||
fKill "progress.sh"
|
||||
(( rc != 0 )) && error "Failed to download $LOC , reason: $rc" && exit 60
|
||||
|
||||
tar --extract --file="$PAT" --directory="$(dirname "$RD")"/. "$(basename "$RD")"
|
||||
rm "$PAT"
|
||||
@@ -138,14 +166,14 @@ fi
|
||||
if [ -f "$RDC" ]; then
|
||||
|
||||
{ xz -dc <"$RDC" >"$TMP/rd" 2>/dev/null; rc=$?; } || :
|
||||
(( rc != 1 )) && error "Failed to unxz $RDC, reason $rc" && exit 91
|
||||
(( rc != 1 )) && error "Failed to unxz $RDC on $FS, reason $rc" && exit 91
|
||||
|
||||
{ (cd "$TMP" && cpio -idm <"$TMP/rd" 2>/dev/null); rc=$?; } || :
|
||||
|
||||
if (( rc != 0 )); then
|
||||
ROOT="N"
|
||||
{ (cd "$TMP" && fakeroot cpio -idmu <"$TMP/rd" 2>/dev/null); rc=$?; } || :
|
||||
(( rc != 0 )) && error "Failed to extract $RDC, reason $rc" && exit 92
|
||||
(( rc != 0 )) && error "Failed to extract $RDC on $FS, reason $rc" && exit 92
|
||||
fi
|
||||
|
||||
rm -rf /run/extract && mkdir -p /run/extract
|
||||
@@ -175,23 +203,33 @@ fi
|
||||
rm -rf "$TMP" && mkdir -p "$TMP"
|
||||
|
||||
info "Install: Downloading $BASE.pat..."
|
||||
html "Install: Downloading DSM from Synology..."
|
||||
|
||||
MSG="Downloading DSM..."
|
||||
PRG="Downloading DSM ([P])..."
|
||||
html "$MSG"
|
||||
|
||||
PAT="/$BASE.pat"
|
||||
rm -f "$PAT"
|
||||
|
||||
SIZE=0
|
||||
[[ "$URL" == *"DSM_VirtualDSM_69057.pat" ]] && SIZE=363837333
|
||||
|
||||
if [[ "$URL" == "file://"* ]]; then
|
||||
|
||||
cp "${URL:7}" "$PAT"
|
||||
|
||||
else
|
||||
|
||||
{ wget "$URL" -O "$PAT" -q --no-check-certificate --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
(( rc != 0 )) && error "Failed to download $URL, reason: $rc" && exit 69
|
||||
/run/progress.sh "$PAT" "$SIZE" "$PRG" &
|
||||
|
||||
{ wget "$URL" -O "$PAT" -q --no-check-certificate --timeout=10 --show-progress "$PROGRESS"; rc=$?; } || :
|
||||
|
||||
fKill "progress.sh"
|
||||
(( rc != 0 )) && error "Failed to download $URL , reason: $rc" && exit 69
|
||||
|
||||
fi
|
||||
|
||||
[ ! -f "$PAT" ] && error "Failed to download $URL" && exit 69
|
||||
[ ! -s "$PAT" ] && error "Failed to download $URL" && exit 69
|
||||
|
||||
SIZE=$(stat -c%s "$PAT")
|
||||
|
||||
@@ -228,7 +266,7 @@ MSG="Preparing system partition..."
|
||||
info "Install: $MSG" && html "$MSG"
|
||||
|
||||
BOOT=$(find "$TMP" -name "*.bin.zip")
|
||||
[ ! -f "$BOOT" ] && error "The PAT file contains no boot image." && exit 67
|
||||
[ ! -s "$BOOT" ] && error "The PAT file contains no boot image." && exit 67
|
||||
|
||||
BOOT=$(echo "$BOOT" | head -c -5)
|
||||
unzip -q -o "$BOOT".zip -d "$TMP"
|
||||
@@ -249,11 +287,11 @@ if ! touch "$SYSTEM"; then
|
||||
error "Could not create file $SYSTEM for the system disk." && exit 98
|
||||
fi
|
||||
|
||||
if [[ "${FS,,}" == "xfs" || "${FS,,}" == "zfs" || "${FS,,}" == "btrfs" || "${FS,,}" == "bcachefs" ]]; then
|
||||
if [[ "${FS,,}" == "btrfs" ]]; then
|
||||
{ chattr +C "$SYSTEM"; } || :
|
||||
FA=$(lsattr "$SYSTEM")
|
||||
if [[ "$FA" != *"C"* ]]; then
|
||||
error "Failed to disable COW for system image $SYSTEM on ${FS^^} filesystem (returned $FA)"
|
||||
error "Failed to disable COW for system image $SYSTEM on ${FS^^} filesystem."
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -289,15 +327,15 @@ IDB="$TMP/indexdb"
|
||||
PKG="$TMP/packages"
|
||||
HDP="$TMP/synohdpack_img"
|
||||
|
||||
[ ! -f "$HDA.tgz" ] && error "The PAT file contains no OS image." && exit 64
|
||||
[ ! -s "$HDA.tgz" ] && error "The PAT file contains no OS image." && exit 64
|
||||
mv "$HDA.tgz" "$HDA.txz"
|
||||
|
||||
[ -d "$PKG" ] && mv "$PKG/" "$MOUNT/.SynoUpgradePackages/"
|
||||
rm -f "$MOUNT/.SynoUpgradePackages/ActiveInsight-"*
|
||||
|
||||
[ -f "$HDP.txz" ] && tar xpfJ "$HDP.txz" --absolute-names -C "$MOUNT/"
|
||||
[ -s "$HDP.txz" ] && tar xpfJ "$HDP.txz" --absolute-names -C "$MOUNT/"
|
||||
|
||||
if [ -f "$IDB.txz" ]; then
|
||||
if [ -s "$IDB.txz" ]; then
|
||||
INDEX_DB="$MOUNT/usr/syno/synoman/indexdb/"
|
||||
mkdir -p "$INDEX_DB"
|
||||
tar xpfJ "$IDB.txz" --absolute-names -C "$INDEX_DB"
|
||||
|
||||
152
src/network.sh
152
src/network.sh
@@ -3,8 +3,10 @@ set -Eeuo pipefail
|
||||
|
||||
# Docker environment variables
|
||||
|
||||
: "${MAC:=""}"
|
||||
: "${DHCP:="N"}"
|
||||
: "${MAC:="02:11:32:AA:BB:CC"}"
|
||||
: "${NETWORK:="Y"}"
|
||||
: "${HOST_PORTS:=""}"
|
||||
|
||||
: "${VM_NET_DEV:=""}"
|
||||
: "${VM_NET_TAP:="dsm"}"
|
||||
@@ -23,17 +25,23 @@ ADD_ERR="Please add the following setting to your container:"
|
||||
|
||||
configureDHCP() {
|
||||
|
||||
# Create a macvtap network for the VM guest
|
||||
# Create the necessary file structure for /dev/vhost-net
|
||||
if [ ! -c /dev/vhost-net ]; then
|
||||
if mknod /dev/vhost-net c 10 238; then
|
||||
chmod 660 /dev/vhost-net
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create a macvtap network for the VM guest
|
||||
{ ip link add link "$VM_NET_DEV" name "$VM_NET_TAP" address "$VM_NET_MAC" type macvtap mode bridge ; rc=$?; } || :
|
||||
|
||||
if (( rc != 0 )); then
|
||||
error "Cannot create macvtap interface. Please make sure the network type is 'macvlan' and not 'ipvlan',"
|
||||
error "and that the NET_ADMIN capability has been added to the container: --cap-add NET_ADMIN" && exit 16
|
||||
error "Cannot create macvtap interface. Please make sure that the network type is 'macvlan' and not 'ipvlan',"
|
||||
error "that your kernel is recent (>4) and supports it, and that the container has the NET_ADMIN capability set." && exit 16
|
||||
fi
|
||||
|
||||
while ! ip link set "$VM_NET_TAP" up; do
|
||||
info "Waiting for address to become available..."
|
||||
info "Waiting for MAC address $VM_NET_MAC to become available..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
@@ -80,16 +88,37 @@ configureDNS() {
|
||||
|
||||
# Set DNS server and gateway
|
||||
DNSMASQ_OPTS="$DNSMASQ_OPTS --dhcp-option=option:dns-server,${VM_NET_IP%.*}.1 --dhcp-option=option:router,${VM_NET_IP%.*}.1"
|
||||
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
||||
|
||||
# Add DNS entry for container
|
||||
DNSMASQ_OPTS="$DNSMASQ_OPTS --address=/host.lan/${VM_NET_IP%.*}.1"
|
||||
|
||||
DNSMASQ_OPTS=$(echo "$DNSMASQ_OPTS" | sed 's/\t/ /g' | tr -s ' ' | sed 's/^ *//')
|
||||
[[ "$DEBUG" == [Yy1]* ]] && set -x
|
||||
$DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
|
||||
|
||||
if ! $DNSMASQ ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}; then
|
||||
error "Failed to start dnsmasq, reason: $?" && exit 29
|
||||
fi
|
||||
{ set +x; } 2>/dev/null
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getPorts() {
|
||||
|
||||
local list=$1
|
||||
|
||||
[ -z "$list" ] && echo "" && return 0
|
||||
|
||||
if [[ "$list" != *","* ]]; then
|
||||
echo " ! --dport $list"
|
||||
else
|
||||
echo " -m multiport ! --dports $list"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
configureNAT() {
|
||||
|
||||
# Create the necessary file structure for /dev/net/tun
|
||||
@@ -101,21 +130,23 @@ configureNAT() {
|
||||
fi
|
||||
|
||||
if [ ! -c /dev/net/tun ]; then
|
||||
error "TUN device missing. $ADD_ERR --cap-add NET_ADMIN" && exit 25
|
||||
error "TUN device missing. $ADD_ERR --device /dev/net/tun --cap-add NET_ADMIN" && exit 25
|
||||
fi
|
||||
|
||||
# Check port forwarding flag
|
||||
if [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
|
||||
{ sysctl -w net.ipv4.ip_forward=1 ; rc=$?; } || :
|
||||
if (( rc != 0 )); then
|
||||
{ sysctl -w net.ipv4.ip_forward=1 > /dev/null; rc=$?; } || :
|
||||
if (( rc != 0 )) || [[ $(< /proc/sys/net/ipv4/ip_forward) -eq 0 ]]; then
|
||||
error "IP forwarding is disabled. $ADD_ERR --sysctl net.ipv4.ip_forward=1" && exit 24
|
||||
fi
|
||||
fi
|
||||
|
||||
local tables="The 'ip_tables' kernel module is not loaded. Try this command: sudo modprobe ip_tables iptable_nat"
|
||||
local tuntap="The 'tun' kernel module is not available. Try this command: 'sudo modprobe tun' or run the container with 'privileged: true'."
|
||||
|
||||
# Create a bridge with a static IP for the VM guest
|
||||
|
||||
VM_NET_IP='20.20.20.21'
|
||||
[[ "$DEBUG" == [Yy1]* ]] && set -x
|
||||
|
||||
{ ip link add dev dockerbridge type bridge ; rc=$?; } || :
|
||||
|
||||
@@ -126,15 +157,17 @@ configureNAT() {
|
||||
ip address add ${VM_NET_IP%.*}.1/24 broadcast ${VM_NET_IP%.*}.255 dev dockerbridge
|
||||
|
||||
while ! ip link set dockerbridge up; do
|
||||
info "Waiting for address to become available..."
|
||||
info "Waiting for IP address to become available..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# QEMU Works with taps, set tap to the bridge created
|
||||
ip tuntap add dev "$VM_NET_TAP" mode tap
|
||||
if ! ip tuntap add dev "$VM_NET_TAP" mode tap; then
|
||||
error "$tuntap" && exit 31
|
||||
fi
|
||||
|
||||
while ! ip link set "$VM_NET_TAP" up promisc on; do
|
||||
info "Waiting for tap to become available..."
|
||||
info "Waiting for TAP to become available..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
@@ -144,22 +177,27 @@ configureNAT() {
|
||||
update-alternatives --set iptables /usr/sbin/iptables-legacy > /dev/null
|
||||
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy > /dev/null
|
||||
|
||||
iptables -t nat -A POSTROUTING -o "$VM_NET_DEV" -j MASQUERADE
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p tcp -j DNAT --to "$VM_NET_IP"
|
||||
exclude=$(getPorts "$HOST_PORTS")
|
||||
|
||||
if ! iptables -t nat -A POSTROUTING -o "$VM_NET_DEV" -j MASQUERADE; then
|
||||
error "$tables" && exit 30
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p tcp${exclude} -j DNAT --to "$VM_NET_IP"
|
||||
iptables -t nat -A PREROUTING -i "$VM_NET_DEV" -d "$IP" -p udp -j DNAT --to "$VM_NET_IP"
|
||||
|
||||
if (( KERNEL > 4 )); then
|
||||
# Hack for guest VMs complaining about "bad udp checksums in 5 packets"
|
||||
iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill || true
|
||||
iptables -A POSTROUTING -t mangle -p udp --dport bootpc -j CHECKSUM --checksum-fill > /dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
{ set +x; } 2>/dev/null
|
||||
[[ "$DEBUG" == [Yy1]* ]] && echo
|
||||
|
||||
NET_OPTS="-netdev tap,ifname=$VM_NET_TAP,script=no,downscript=no,id=hostnet0"
|
||||
|
||||
{ exec 40>>/dev/vhost-net; rc=$?; } 2>/dev/null || :
|
||||
(( rc == 0 )) && NET_OPTS="$NET_OPTS,vhost=on,vhostfd=40"
|
||||
if [ -c /dev/vhost-net ]; then
|
||||
{ exec 40>>/dev/vhost-net; rc=$?; } 2>/dev/null || :
|
||||
(( rc == 0 )) && NET_OPTS="$NET_OPTS,vhost=on,vhostfd=40"
|
||||
fi
|
||||
|
||||
configureDNS
|
||||
|
||||
@@ -168,22 +206,28 @@ configureNAT() {
|
||||
|
||||
closeNetwork() {
|
||||
|
||||
exec 30<&- || true
|
||||
exec 40<&- || true
|
||||
|
||||
if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
# Shutdown nginx
|
||||
nginx -s stop 2> /dev/null
|
||||
fWait "nginx"
|
||||
|
||||
fi
|
||||
|
||||
[[ "$NETWORK" != [Yy1]* ]] && return 0
|
||||
|
||||
exec 30<&- || true
|
||||
exec 40<&- || true
|
||||
|
||||
if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
ip link set "$VM_NET_TAP" down || true
|
||||
ip link delete "$VM_NET_TAP" || true
|
||||
|
||||
else
|
||||
|
||||
local pid="/var/run/dnsmasq.pid"
|
||||
[ -f "$pid" ] && pKill "$(<"$pid")"
|
||||
[ -s "$pid" ] && pKill "$(<"$pid")"
|
||||
|
||||
ip link set "$VM_NET_TAP" down promisc off || true
|
||||
ip link delete "$VM_NET_TAP" || true
|
||||
@@ -196,6 +240,23 @@ closeNetwork() {
|
||||
return 0
|
||||
}
|
||||
|
||||
checkOS() {
|
||||
|
||||
local name
|
||||
local os=""
|
||||
name=$(uname -a)
|
||||
|
||||
[[ "${name,,}" == *"darwin"* ]] && os="MacOS"
|
||||
[[ "${name,,}" == *"microsoft"* ]] && os="Windows"
|
||||
|
||||
if [ -n "$os" ]; then
|
||||
error "You are using Docker Desktop for $os which does not support macvlan, please revert to bridge networking!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
getInfo() {
|
||||
|
||||
if [ -z "$VM_NET_DEV" ]; then
|
||||
@@ -209,14 +270,26 @@ getInfo() {
|
||||
error "$ADD_ERR -e \"VM_NET_DEV=NAME\" to specify another interface name." && exit 27
|
||||
fi
|
||||
|
||||
if [ -z "$VM_NET_MAC" ]; then
|
||||
local file="$STORAGE/dsm.mac"
|
||||
[ -s "$file" ] && VM_NET_MAC=$(<"$file")
|
||||
if [ -z "$VM_NET_MAC" ]; then
|
||||
# Generate MAC address based on Docker container ID in hostname
|
||||
VM_NET_MAC=$(echo "$HOST" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:11:32:\3:\4:\5/')
|
||||
echo "${VM_NET_MAC^^}" > "$file"
|
||||
fi
|
||||
fi
|
||||
|
||||
VM_NET_MAC="${VM_NET_MAC^^}"
|
||||
VM_NET_MAC="${VM_NET_MAC//-/:}"
|
||||
|
||||
if [[ ${#VM_NET_MAC} == 12 ]]; then
|
||||
m="$VM_NET_MAC"
|
||||
VM_NET_MAC="${m:0:2}:${m:2:2}:${m:4:2}:${m:6:2}:${m:8:2}:${m:10:2}"
|
||||
fi
|
||||
|
||||
if [[ ${#VM_NET_MAC} != 17 ]]; then
|
||||
error "Invalid mac address: '$VM_NET_MAC', should be 12 or 17 digits long!" && exit 28
|
||||
error "Invalid MAC address: '$VM_NET_MAC', should be 12 or 17 digits long!" && exit 28
|
||||
fi
|
||||
|
||||
GATEWAY=$(ip r | grep default | awk '{print $3}')
|
||||
@@ -230,25 +303,30 @@ getInfo() {
|
||||
# Configure Network
|
||||
# ######################################
|
||||
|
||||
if [ ! -c /dev/vhost-net ]; then
|
||||
if mknod /dev/vhost-net c 10 238; then
|
||||
chmod 660 /dev/vhost-net
|
||||
fi
|
||||
if [[ "$NETWORK" != [Yy1]* ]]; then
|
||||
NET_OPTS=""
|
||||
return 0
|
||||
fi
|
||||
|
||||
getInfo
|
||||
html "Initializing network..."
|
||||
|
||||
if [[ "$DEBUG" == [Yy1]* ]]; then
|
||||
info "Container IP is $IP with gateway $GATEWAY on interface $VM_NET_DEV" && echo
|
||||
info "Host: $HOST IP: $IP Gateway: $GATEWAY Interface: $VM_NET_DEV MAC: $VM_NET_MAC"
|
||||
[ -f /etc/resolv.conf ] && grep '^nameserver*' /etc/resolv.conf
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ "$IP" == "172.17."* ]]; then
|
||||
warn "your container IP starts with 172.17.* which will cause conflicts when you install the Container Manager package inside DSM!"
|
||||
fi
|
||||
|
||||
if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
! checkOS && exit 19
|
||||
|
||||
if [[ "$GATEWAY" == "172."* ]]; then
|
||||
if [[ "$DEBUG" != [Yy1]* ]]; then
|
||||
error "You can only enable DHCP while the container is on a macvlan network!" && exit 26
|
||||
fi
|
||||
warn "your gateway IP starts with 172.* which is often a sign that you are not on a macvlan network (required for DHCP)!"
|
||||
fi
|
||||
|
||||
# Configuration for DHCP IP
|
||||
@@ -259,6 +337,10 @@ if [[ "$DHCP" == [Yy1]* ]]; then
|
||||
|
||||
else
|
||||
|
||||
if [[ "$GATEWAY" != "172."* ]]; then
|
||||
! checkOS && exit 19
|
||||
fi
|
||||
|
||||
# Shutdown nginx
|
||||
nginx -s stop 2> /dev/null
|
||||
fWait "nginx"
|
||||
|
||||
25
src/power.sh
25
src/power.sh
@@ -10,10 +10,11 @@ API_HOST="127.0.0.1:2210"
|
||||
QEMU_TERM=""
|
||||
QEMU_PORT=7100
|
||||
QEMU_TIMEOUT=50
|
||||
QEMU_PID="/run/shm/qemu.pid"
|
||||
QEMU_LOG="/run/shm/qemu.log"
|
||||
QEMU_OUT="/run/shm/qemu.out"
|
||||
QEMU_END="/run/shm/qemu.end"
|
||||
QEMU_DIR="/run/shm"
|
||||
QEMU_PID="$QEMU_DIR/qemu.pid"
|
||||
QEMU_LOG="$QEMU_DIR/qemu.log"
|
||||
QEMU_OUT="$QEMU_DIR/qemu.out"
|
||||
QEMU_END="$QEMU_DIR/qemu.end"
|
||||
|
||||
if [[ "$KVM" == [Nn]* ]]; then
|
||||
API_TIMEOUT=$(( API_TIMEOUT*2 ))
|
||||
@@ -34,7 +35,9 @@ finish() {
|
||||
local pid
|
||||
local reason=$1
|
||||
|
||||
if [ -f "$QEMU_PID" ]; then
|
||||
touch "$QEMU_END"
|
||||
|
||||
if [ -s "$QEMU_PID" ]; then
|
||||
|
||||
pid=$(<"$QEMU_PID")
|
||||
echo && error "Forcefully terminating QEMU process, reason: $reason..."
|
||||
@@ -43,7 +46,7 @@ finish() {
|
||||
while isAlive "$pid"; do
|
||||
sleep 1
|
||||
# Workaround for zombie pid
|
||||
[ ! -f "$QEMU_PID" ] && break
|
||||
[ ! -s "$QEMU_PID" ] && break
|
||||
done
|
||||
fi
|
||||
|
||||
@@ -62,7 +65,7 @@ terminal() {
|
||||
|
||||
local dev=""
|
||||
|
||||
if [ -f "$QEMU_OUT" ]; then
|
||||
if [ -s "$QEMU_OUT" ]; then
|
||||
|
||||
local msg
|
||||
msg=$(<"$QEMU_OUT")
|
||||
@@ -98,7 +101,6 @@ terminal() {
|
||||
|
||||
_graceful_shutdown() {
|
||||
|
||||
local cnt=0
|
||||
local code=$?
|
||||
local pid url response
|
||||
|
||||
@@ -112,7 +114,7 @@ _graceful_shutdown() {
|
||||
touch "$QEMU_END"
|
||||
echo && info "Received $1 signal, sending shutdown command..."
|
||||
|
||||
if [ ! -f "$QEMU_PID" ]; then
|
||||
if [ ! -s "$QEMU_PID" ]; then
|
||||
echo && error "QEMU PID file does not exist?"
|
||||
finish "$code" && return "$code"
|
||||
fi
|
||||
@@ -144,6 +146,8 @@ _graceful_shutdown() {
|
||||
|
||||
fi
|
||||
|
||||
local cnt=0
|
||||
|
||||
while [ "$cnt" -lt "$QEMU_TIMEOUT" ]; do
|
||||
|
||||
! isAlive "$pid" && break
|
||||
@@ -154,7 +158,7 @@ _graceful_shutdown() {
|
||||
[[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt/$QEMU_TIMEOUT)"
|
||||
|
||||
# Workaround for zombie pid
|
||||
[ ! -f "$QEMU_PID" ] && break
|
||||
[ ! -s "$QEMU_PID" ] && break
|
||||
|
||||
done
|
||||
|
||||
@@ -167,6 +171,7 @@ _graceful_shutdown() {
|
||||
|
||||
MON_OPTS="\
|
||||
-pidfile $QEMU_PID \
|
||||
-name $PROCESS,process=$PROCESS,debug-threads=on \
|
||||
-monitor telnet:localhost:$QEMU_PORT,server,nowait,nodelay"
|
||||
|
||||
if [[ "$CONSOLE" != [Yy]* ]]; then
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
: "${DHCP:="N"}"
|
||||
: "${NETWORK:="Y"}"
|
||||
|
||||
[[ "$NETWORK" != [Yy1]* ]] && exit 0
|
||||
|
||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n" >&2; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
||||
@@ -18,7 +21,7 @@ resp_err="Guest returned an invalid response:"
|
||||
curl_err="Failed to connect to guest: curl error"
|
||||
jq_err="Failed to parse response from guest: jq error"
|
||||
|
||||
while [ ! -f "$file" ]
|
||||
while [ ! -s "$file" ]
|
||||
do
|
||||
|
||||
# Check if not shutting down
|
||||
@@ -27,7 +30,7 @@ do
|
||||
sleep 3
|
||||
|
||||
[ -f "$shutdown" ] && exit 1
|
||||
[ -f "$file" ] && break
|
||||
[ -s "$file" ] && break
|
||||
|
||||
# Retrieve network info from guest VM
|
||||
{ json=$(curl -m 20 -sk "$url"); rc=$?; } || :
|
||||
@@ -101,3 +104,5 @@ info "-----------------------------------------------------------"
|
||||
info " You can now login to DSM at $msg"
|
||||
info "-----------------------------------------------------------"
|
||||
echo "" >&2
|
||||
|
||||
exit 0
|
||||
|
||||
70
src/proc.sh
70
src/proc.sh
@@ -5,10 +5,11 @@ set -Eeuo pipefail
|
||||
|
||||
: "${KVM:="Y"}"
|
||||
: "${HOST_CPU:=""}"
|
||||
: "${CPU_MODEL:="host"}"
|
||||
: "${CPU_FEATURES:="+ssse3,+sse4.1,+sse4.2"}"
|
||||
: "${CPU_FLAGS:=""}"
|
||||
: "${CPU_MODEL:=""}"
|
||||
: "${DEF_MODEL:="qemu64"}"
|
||||
|
||||
[ "$ARCH" != "amd64" ] && KVM="N"
|
||||
[[ "${ARCH,,}" != "amd64" ]] && KVM="N"
|
||||
|
||||
if [[ "$KVM" != [Nn]* ]]; then
|
||||
|
||||
@@ -20,7 +21,8 @@ if [[ "$KVM" != [Nn]* ]]; then
|
||||
if ! sh -c 'echo -n > /dev/kvm' &> /dev/null; then
|
||||
KVM_ERR="(no write access)"
|
||||
else
|
||||
if ! grep -q -e vmx -e svm /proc/cpuinfo; then
|
||||
flags=$(sed -ne '/^flags/s/^.*: //p' /proc/cpuinfo)
|
||||
if ! grep -qw "vmx\|svm" <<< "$flags"; then
|
||||
KVM_ERR="(vmx/svm disabled)"
|
||||
fi
|
||||
fi
|
||||
@@ -28,39 +30,75 @@ if [[ "$KVM" != [Nn]* ]]; then
|
||||
|
||||
if [ -n "$KVM_ERR" ]; then
|
||||
KVM="N"
|
||||
error "KVM acceleration not detected $KVM_ERR, this will cause a major loss of performance."
|
||||
error "See the FAQ on how to enable it, or continue without KVM by setting KVM=N (not recommended)."
|
||||
[[ "$DEBUG" != [Yy1]* ]] && exit 88
|
||||
if [[ "$OSTYPE" =~ ^darwin ]]; then
|
||||
warn "you are using MacOS which has no KVM support, this will cause a major loss of performance."
|
||||
else
|
||||
if grep -qi Microsoft /proc/version; then
|
||||
warn "you are using Windows 10 which has no KVM support, this will cause a major loss of performance."
|
||||
else
|
||||
error "KVM acceleration not available $KVM_ERR, this will cause a major loss of performance."
|
||||
error "See the FAQ on how to enable it, or continue without KVM by setting KVM=N (not recommended)."
|
||||
[[ "$DEBUG" != [Yy1]* ]] && exit 88
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [[ "$KVM" != [Nn]* ]]; then
|
||||
|
||||
KVM_OPTS=",accel=kvm -enable-kvm"
|
||||
CPU_FEATURES="kvm=on,l3-cache=on"
|
||||
KVM_OPTS=",accel=kvm -enable-kvm -global kvm-pit.lost_tick_policy=discard"
|
||||
|
||||
if ! grep -qE '^flags.* (sse4_2)' /proc/cpuinfo; then
|
||||
error "Your host CPU does not have the SSE4.2 instruction set that Virtual DSM requires to boot."
|
||||
error "Disable KVM by setting KVM=N to emulate a compatible CPU, at the cost of performance."
|
||||
[[ "$DEBUG" != [Yy1]* ]] && exit 89
|
||||
if ! grep -qw "sse4_2" <<< "$flags"; then
|
||||
info "Your CPU does not have the SSE4 instruction set that Virtual DSM requires, it will be emulated..."
|
||||
[ -z "$CPU_MODEL" ] && CPU_MODEL="$DEF_MODEL"
|
||||
CPU_FEATURES="$CPU_FEATURES,+ssse3,+sse4.1,+sse4.2"
|
||||
fi
|
||||
|
||||
if [ -z "$CPU_MODEL" ]; then
|
||||
CPU_MODEL="host"
|
||||
CPU_FEATURES="$CPU_FEATURES,migratable=no"
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
KVM_OPTS=""
|
||||
CPU_FEATURES="l3-cache=on"
|
||||
|
||||
if [[ "$CPU_MODEL" == "host"* ]]; then
|
||||
if [[ "$ARCH" == "amd64" ]]; then
|
||||
KVM_OPTS=" -accel tcg,thread=multi"
|
||||
fi
|
||||
|
||||
if [ -z "$CPU_MODEL" ]; then
|
||||
if [[ "$ARCH" == "amd64" ]]; then
|
||||
CPU_MODEL="max,$CPU_FEATURES"
|
||||
CPU_MODEL="max"
|
||||
CPU_FEATURES="$CPU_FEATURES,migratable=no"
|
||||
else
|
||||
CPU_MODEL="qemu64,$CPU_FEATURES"
|
||||
CPU_MODEL="$DEF_MODEL"
|
||||
fi
|
||||
fi
|
||||
|
||||
CPU_FEATURES="$CPU_FEATURES,+ssse3,+sse4.1,+sse4.2"
|
||||
|
||||
fi
|
||||
|
||||
if [ -z "$CPU_FLAGS" ]; then
|
||||
if [ -z "$CPU_FEATURES" ]; then
|
||||
CPU_FLAGS="$CPU_MODEL"
|
||||
else
|
||||
CPU_FLAGS="$CPU_MODEL,$CPU_FEATURES"
|
||||
fi
|
||||
else
|
||||
if [ -z "$CPU_FEATURES" ]; then
|
||||
CPU_FLAGS="$CPU_MODEL,$CPU_FLAGS"
|
||||
else
|
||||
CPU_FLAGS="$CPU_MODEL,$CPU_FEATURES,$CPU_FLAGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$HOST_CPU" ]; then
|
||||
HOST_CPU=$(lscpu | grep 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
HOST_CPU=$(lscpu | grep -m 1 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
fi
|
||||
|
||||
if [ -n "$HOST_CPU" ]; then
|
||||
|
||||
38
src/progress.sh
Normal file
38
src/progress.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
escape () {
|
||||
local s
|
||||
s=${1//&/\&}
|
||||
s=${s//</\<}
|
||||
s=${s//>/\>}
|
||||
s=${s//'"'/\"}
|
||||
printf -- %s "$s"
|
||||
return 0
|
||||
}
|
||||
|
||||
file="$1"
|
||||
total="$2"
|
||||
body=$(escape "$3")
|
||||
info="/run/shm/msg.html"
|
||||
|
||||
if [[ "$body" == *"..." ]]; then
|
||||
body="<p class=\"loading\">${body/.../}</p>"
|
||||
fi
|
||||
|
||||
while true
|
||||
do
|
||||
if [ -s "$file" ]; then
|
||||
bytes=$(du -sb "$file" | cut -f1)
|
||||
if (( bytes > 1000 )); then
|
||||
if [ -z "$total" ] || [[ "$total" == "0" ]]; then
|
||||
size=$(numfmt --to=iec --suffix=B "$bytes" | sed -r 's/([A-Z])/ \1/')
|
||||
else
|
||||
size=$(printf '%.1f\n' "$((bytes*100*100/total))e-2")
|
||||
size="$size%"
|
||||
fi
|
||||
echo "${body//(\[P\])/($size)}"> "$info"
|
||||
fi
|
||||
fi
|
||||
sleep 1 & wait $!
|
||||
done
|
||||
65
src/reset.sh
65
src/reset.sh
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "$1" "\E[0m\n"; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: $1" "\E[0m\n" >&2; }
|
||||
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: $1" "\E[0m\n" >&2; }
|
||||
info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "${1:-}" "\E[0m\n"; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: ${1:-}" "\E[0m\n" >&2; }
|
||||
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: ${1:-}" "\E[0m\n" >&2; }
|
||||
|
||||
trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
|
||||
|
||||
@@ -12,7 +12,6 @@ trap 'error "Status $? while: $BASH_COMMAND (line $LINENO/$BASH_LINENO)"' ERR
|
||||
|
||||
echo "❯ Starting $APP for Docker v$(</run/version)..."
|
||||
echo "❯ For support visit $SUPPORT"
|
||||
echo
|
||||
|
||||
# Docker environment variables
|
||||
|
||||
@@ -28,17 +27,30 @@ echo
|
||||
|
||||
# Helper variables
|
||||
|
||||
PROCESS="${APP,,}"
|
||||
PROCESS="${PROCESS// /-}"
|
||||
|
||||
STORAGE="/storage"
|
||||
INFO="/dev/shm/msg.html"
|
||||
INFO="/run/shm/msg.html"
|
||||
PAGE="/run/shm/index.html"
|
||||
TEMPLATE="/var/www/index.html"
|
||||
FOOTER1="$APP for Docker v$(</run/version)"
|
||||
FOOTER2="<a href='$SUPPORT'>$SUPPORT</a>"
|
||||
|
||||
KERNEL=$(uname -r | cut -b 1)
|
||||
MINOR=$(uname -r | cut -d '.' -f2)
|
||||
SYS=$(uname -r)
|
||||
HOST=$(hostname -s)
|
||||
KERNEL=$(echo "$SYS" | cut -b 1)
|
||||
MINOR=$(echo "$SYS" | cut -d '.' -f2)
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
VERS=$(qemu-system-x86_64 --version | head -n 1 | cut -d '(' -f 1)
|
||||
CPU=$(lscpu | grep -m 1 'Model name' | cut -f 2 -d ":" | awk '{$1=$1}1' | sed 's# @.*##g' | sed s/"(R)"//g | sed 's/[^[:alnum:] ]\+/ /g' | sed 's/ */ /g')
|
||||
|
||||
# Check system
|
||||
|
||||
if [ ! -d "/dev/shm" ]; then
|
||||
error "Directory /dev/shm not found!" && exit 14
|
||||
else
|
||||
[ ! -d "/run/shm" ] && ln -s /dev/shm /run/shm
|
||||
fi
|
||||
|
||||
# Check folder
|
||||
|
||||
@@ -46,12 +58,37 @@ if [ ! -d "$STORAGE" ]; then
|
||||
error "Storage folder ($STORAGE) not found!" && exit 13
|
||||
fi
|
||||
|
||||
if [ ! -d "/run/shm" ]; then
|
||||
if [ -d "/dev/shm" ]; then
|
||||
ln -s /dev/shm /run/shm
|
||||
else
|
||||
error "Folder /dev/shm not found!" && exit 14
|
||||
fi
|
||||
# Check filesystem
|
||||
FS=$(stat -f -c %T "$STORAGE")
|
||||
|
||||
if [[ "${FS,,}" == "ecryptfs" ]] || [[ "${FS,,}" == "tmpfs" ]]; then
|
||||
DISK_IO="threads"
|
||||
DISK_CACHE="writeback"
|
||||
fi
|
||||
|
||||
# Read memory
|
||||
RAM_AVAIL=$(free -b | grep -m 1 Mem: | awk '{print $7}')
|
||||
RAM_TOTAL=$(free -b | grep -m 1 Mem: | awk '{print $2}')
|
||||
RAM_SIZE=$(echo "${RAM_SIZE^^}" | sed 's/MB/M/g;s/GB/G/g;s/TB/T/g')
|
||||
RAM_WANTED=$(numfmt --from=iec "$RAM_SIZE")
|
||||
AVAIL_GB=$(( (RAM_AVAIL + 1073741823)/1073741824 ))
|
||||
TOTAL_GB=$(( (RAM_TOTAL + 1073741823)/1073741824 ))
|
||||
WANTED_GB=$(( (RAM_WANTED + 1073741823)/1073741824 ))
|
||||
|
||||
# Print system info
|
||||
SYS="${SYS/-generic/}"
|
||||
FS="${FS/ext2\/ext3/ext4}"
|
||||
SPACE=$(df --output=avail -B 1 "$STORAGE" | tail -n 1)
|
||||
SPACE_GB=$(( (SPACE + 1073741823)/1073741824 ))
|
||||
|
||||
echo "❯ CPU: ${CPU} | RAM: $AVAIL_GB/$TOTAL_GB GB | DISK: $SPACE_GB GB (${FS}) | HOST: ${SYS}..."
|
||||
echo
|
||||
|
||||
# Check memory
|
||||
|
||||
if (( (RAM_WANTED + 500000000) > RAM_AVAIL )); then
|
||||
error "Your configured RAM_SIZE of $WANTED_GB GB is higher than the $AVAIL_GB GB of memory available, please set a lower value."
|
||||
exit 17
|
||||
fi
|
||||
|
||||
# Cleanup files
|
||||
|
||||
@@ -9,6 +9,21 @@ set -Eeuo pipefail
|
||||
: "${HOST_MODEL:=""}"
|
||||
: "${GUEST_SERIAL:=""}"
|
||||
|
||||
if [ -n "$HOST_MAC" ]; then
|
||||
|
||||
HOST_MAC="${HOST_MAC//-/:}"
|
||||
|
||||
if [[ ${#HOST_MAC} == 12 ]]; then
|
||||
m="$HOST_MAC"
|
||||
HOST_MAC="${m:0:2}:${m:2:2}:${m:4:2}:${m:6:2}:${m:8:2}:${m:10:2}"
|
||||
fi
|
||||
|
||||
if [[ ${#HOST_MAC} != 17 ]]; then
|
||||
error "Invalid HOST_MAC address: '$HOST_MAC', should be 12 or 17 digits long!" && exit 28
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
HOST_ARGS=()
|
||||
HOST_ARGS+=("-cpu=$CPU_CORES")
|
||||
HOST_ARGS+=("-cpu_arch=$HOST_CPU")
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
body {
|
||||
color: white;
|
||||
background-color: #125bdb;
|
||||
font-family: Verdana, Arial, sans-serif;
|
||||
font-smoothing: antialiased;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
#info {
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
#content {
|
||||
@@ -17,6 +24,7 @@ footer {
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
color: #0c8aeb;
|
||||
text-shadow: 0 0 1px #0c8aeb;
|
||||
}
|
||||
|
||||
#empty {
|
||||
@@ -33,8 +41,13 @@ a:visited {
|
||||
|
||||
footer a:link,
|
||||
footer a:visited,
|
||||
footer a:active { color: #0c8aeb; }
|
||||
footer a:hover { color: #73e6ff; }
|
||||
footer a:active {
|
||||
color: #0c8aeb;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #73e6ff;
|
||||
}
|
||||
|
||||
.loading:after {
|
||||
content: " .";
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 5000 default_server;
|
||||
listen [::]:5000 default_server;
|
||||
|
||||
autoindex on;
|
||||
tcp_nodelay on;
|
||||
|
||||
Reference in New Issue
Block a user