├── .gitignore
├── .github
├── logo.png
├── renovate.json
├── dependabot.yml
└── workflows
│ ├── test.yml
│ ├── check.yml
│ ├── hub.yml
│ ├── review.yml
│ └── build.yml
├── users.conf
├── .dockerignore
├── compose.yml
├── smb.conf
├── Dockerfile
├── license.md
├── readme.md
└── samba.sh
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockur/samba/HEAD/.github/logo.png
--------------------------------------------------------------------------------
/users.conf:
--------------------------------------------------------------------------------
1 | #username:UID:groupname:GID:password:homedir
2 | samba:1000:smb:1000:secret
3 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:recommended", ":disableDependencyDashboard"],
4 | "forkProcessing": "enabled"
5 | }
6 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .dockerignore
2 | .github
3 | .gitignore
4 | .gitlab-ci.yml
5 | .gitmodules
6 | .vscode
7 | Dockerfile
8 | Dockerfile.archive
9 | compose.yml
10 | compose.yaml
11 | docker-compose.yml
12 | docker-compose.yaml
13 | renovate.json
14 |
15 | *.md
16 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: docker
4 | directory: /
5 | schedule:
6 | interval: weekly
7 | - package-ecosystem: github-actions
8 | directory: /
9 | schedule:
10 | interval: weekly
11 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches-ignore:
4 | - master
5 | paths:
6 | - '**/*.sh'
7 | - 'Dockerfile'
8 |
9 | pull_request:
10 | paths:
11 | - '**/*.sh'
12 | - 'Dockerfile'
13 |
14 | name: "Test"
15 | permissions: {}
16 |
17 | jobs:
18 | shellcheck:
19 | name: Test
20 | uses: ./.github/workflows/check.yml
21 |
--------------------------------------------------------------------------------
/compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | samba:
3 | image: dockurr/samba
4 | container_name: samba
5 | environment:
6 | NAME: "Data"
7 | USER: "samba"
8 | PASS: "secret"
9 | RW: true # Optional, default true
10 | UID: 1000 # Optional, default 1000
11 | GID: 1000 # Optional, default 1000
12 | ports:
13 | - 445:445
14 | volumes:
15 | - ./samba:/storage
16 | restart: always
17 |
--------------------------------------------------------------------------------
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | on: [workflow_call]
2 | name: "Check"
3 | permissions: {}
4 |
5 | jobs:
6 | shellcheck:
7 | name: shellcheck
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v5
11 | - name: Run ShellCheck
12 | uses: ludeeus/action-shellcheck@master
13 | env:
14 | SHELLCHECK_OPTS: -x
15 | - name: Lint Dockerfile
16 | uses: hadolint/hadolint-action@v3.3.0
17 | with:
18 | dockerfile: Dockerfile
19 | ignore: DL3018
20 | failure-threshold: warning
21 |
--------------------------------------------------------------------------------
/smb.conf:
--------------------------------------------------------------------------------
1 | [global]
2 | server string = samba
3 | idmap config * : range = 3000-7999
4 | security = user
5 | server min protocol = SMB2
6 |
7 | # disable printing services
8 | load printers = no
9 | printing = bsd
10 | printcap name = /dev/null
11 | disable spoolss = yes
12 |
13 | [Data]
14 | path = /storage
15 | comment = Shared
16 | valid users = @smb
17 | browseable = yes
18 | writable = yes
19 | read only = no
20 | force user = root
21 | force group = root
22 |
--------------------------------------------------------------------------------
/.github/workflows/hub.yml:
--------------------------------------------------------------------------------
1 | name: Update
2 | on:
3 | push:
4 | branches:
5 | - master
6 | paths:
7 | - readme.md
8 | - .github/workflows/hub.yml
9 |
10 | jobs:
11 | dockerHubDescription:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v5
15 | -
16 | name: Docker Hub Description
17 | uses: peter-evans/dockerhub-description@v5
18 | with:
19 | username: ${{ secrets.DOCKERHUB_USERNAME }}
20 | password: ${{ secrets.DOCKERHUB_TOKEN }}
21 | repository: ${{ secrets.DOCKERHUB_REPO }}
22 | short-description: ${{ github.event.repository.description }}
23 | readme-filepath: ./readme.md
24 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:1
2 |
3 | FROM alpine:edge
4 |
5 | RUN set -eu && \
6 | apk --no-cache add \
7 | tini \
8 | bash \
9 | samba \
10 | tzdata \
11 | shadow && \
12 | addgroup -S smb && \
13 | rm -f /etc/samba/smb.conf && \
14 | rm -rf /tmp/* /var/cache/apk/*
15 |
16 | COPY --chmod=755 samba.sh /usr/bin/samba.sh
17 | COPY --chmod=664 smb.conf /etc/samba/smb.default
18 |
19 | VOLUME /storage
20 | EXPOSE 139 445
21 |
22 | ENV NAME="Data"
23 | ENV USER="samba"
24 | ENV PASS="secret"
25 |
26 | ENV UID=1000
27 | ENV GID=1000
28 | ENV RW=true
29 |
30 | HEALTHCHECK --interval=60s --timeout=15s CMD smbclient --configfile=/etc/samba.conf -L \\localhost -U % -m SMB3
31 |
32 | ENTRYPOINT ["/sbin/tini", "--", "/usr/bin/samba.sh"]
33 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/.github/workflows/review.yml:
--------------------------------------------------------------------------------
1 | on:
2 | pull_request:
3 |
4 | name: "Review"
5 |
6 | permissions:
7 | contents: read
8 | pull-requests: write
9 | checks: write
10 |
11 | jobs:
12 | review:
13 | name: review
14 | runs-on: ubuntu-latest
15 | steps:
16 | -
17 | name: Checkout
18 | uses: actions/checkout@v5
19 | -
20 | name: Spelling
21 | uses: reviewdog/action-misspell@v1
22 | with:
23 | locale: "US"
24 | level: warning
25 | pattern: |
26 | *.md
27 | *.sh
28 | reporter: github-pr-review
29 | github_token: ${{ secrets.GITHUB_TOKEN }}
30 | -
31 | name: Hadolint
32 | uses: reviewdog/action-hadolint@v1
33 | with:
34 | level: warning
35 | reporter: github-pr-review
36 | hadolint_ignore: DL3018
37 | github_token: ${{ secrets.GITHUB_TOKEN }}
38 | -
39 | name: YamlLint
40 | uses: reviewdog/action-yamllint@v1
41 | with:
42 | level: warning
43 | reporter: github-pr-review
44 | github_token: ${{ secrets.GITHUB_TOKEN }}
45 | -
46 | name: ActionLint
47 | uses: reviewdog/action-actionlint@v1
48 | with:
49 | level: warning
50 | reporter: github-pr-review
51 | github_token: ${{ secrets.GITHUB_TOKEN }}
52 | -
53 | name: Shellformat
54 | uses: reviewdog/action-shfmt@v1
55 | with:
56 | level: warning
57 | shfmt_flags: "-i 2 -ci -bn"
58 | github_token: ${{ secrets.GITHUB_TOKEN }}
59 | -
60 | name: Shellcheck
61 | uses: reviewdog/action-shellcheck@v1
62 | with:
63 | level: warning
64 | reporter: github-pr-review
65 | shellcheck_flags: -x
66 | github_token: ${{ secrets.GITHUB_TOKEN }}
67 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 |
6 | [![Build]][build_url]
7 | [![Version]][tag_url]
8 | [![Size]][tag_url]
9 | [![Package]][pkg_url]
10 | [![Pulls]][hub_url]
11 |
12 |
13 |
14 | Docker container of [Samba](https://www.samba.org/), an implementation of the Windows SMB networking protocol.
15 |
16 | ## Usage 🐳
17 |
18 | ##### Via Docker Compose:
19 |
20 | ```yaml
21 | services:
22 | samba:
23 | image: dockurr/samba
24 | container_name: samba
25 | environment:
26 | NAME: "Data"
27 | USER: "samba"
28 | PASS: "secret"
29 | ports:
30 | - 445:445
31 | volumes:
32 | - ./samba:/storage
33 | restart: always
34 | ```
35 |
36 | ##### Via Docker CLI:
37 |
38 | ```bash
39 | docker run -it --rm --name samba -p 445:445 -e "NAME=Data" -e "USER=samba" -e "PASS=secret" -v "${PWD:-.}/samba:/storage" docker.io/dockurr/samba
40 | ```
41 |
42 | ## Configuration ⚙️
43 |
44 | ### How do I choose the location of the shared folder?
45 |
46 | To change the location of the shared folder, include the following bind mount in your compose file:
47 |
48 | ```yaml
49 | volumes:
50 | - ./samba:/storage
51 | ```
52 |
53 | Replace the example path `./samba` with the desired folder or named volume.
54 |
55 | ### How do I modify the display name of the shared folder?
56 |
57 | You can change the display name of the shared folder by adding the following environment variable:
58 |
59 | ```yaml
60 | environment:
61 | NAME: "Data"
62 | ```
63 |
64 | ### How do I connect to the shared folder?
65 |
66 | To connect to the shared folder enter: `\\192.168.0.2\Data` in Windows Explorer.
67 |
68 | > [!NOTE]
69 | > Replace the example IP address above with that of your host.
70 |
71 | ### How do I modify the default credentials?
72 |
73 | You can set the `USER` and `PASS` environment variables to modify the credentials from their default values: user `samba` with password `secret`.
74 |
75 | ```yaml
76 | environment:
77 | USER: "samba"
78 | PASS: "secret"
79 | ```
80 |
81 | ### How do I modify the permissions?
82 |
83 | You can set `UID` and `GID` environment variables to change the user and group ID.
84 |
85 | ```yaml
86 | environment:
87 | UID: "1002"
88 | GID: "1005"
89 | ```
90 |
91 | To mark the share as read-only, add the variable `RW: "false"`.
92 |
93 | ### How do I modify other settings?
94 |
95 | If you need more advanced features, you can completely override the default configuration by modifying the [smb.conf](https://github.com/dockur/samba/blob/master/smb.conf) file in this repo, and binding your custom config to the container like this:
96 |
97 | ```yaml
98 | volumes:
99 | - ./smb.conf:/etc/samba/smb.conf
100 | ```
101 |
102 | ### How do I configure multiple users?
103 |
104 | If you want to configure multiple users, you can bind the [users.conf](https://github.com/dockur/samba/blob/master/users.conf) file to the container as follows:
105 |
106 | ```yaml
107 | volumes:
108 | - ./users.conf:/etc/samba/users.conf
109 | ```
110 |
111 | Each line inside that file contains a `:` separated list of attributes describing the user to be created.
112 |
113 | `username:UID:groupname:GID:password:homedir`
114 |
115 | where:
116 | - `username` The textual name of the user.
117 | - `UID` The numerical id of the user.
118 | - `groupname` The textual name of the primary user group.
119 | - `GID` The numerical id of the primary user group.
120 | - `password` The clear text password of the user. The password can not contain `:`,`\n` or `\r`.
121 | - `homedir` Optional field for setting the home directory of the user.
122 |
123 | ## Stars 🌟
124 | [](https://starchart.cc/dockur/samba)
125 |
126 | [build_url]: https://github.com/dockur/samba/
127 | [hub_url]: https://hub.docker.com/r/dockurr/samba
128 | [tag_url]: https://hub.docker.com/r/dockurr/samba/tags
129 | [pkg_url]: https://github.com/dockur/samba/pkgs/container/samba
130 |
131 | [Build]: https://github.com/dockur/samba/actions/workflows/build.yml/badge.svg
132 | [Size]: https://img.shields.io/docker/image-size/dockurr/samba/latest?color=066da5&label=size
133 | [Pulls]: https://img.shields.io/docker/pulls/dockurr/samba.svg?style=flat&label=pulls&logo=docker
134 | [Version]: https://img.shields.io/docker/v/dockurr/samba/latest?arch=amd64&sort=semver&color=066da5
135 | [Package]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fipitio.github.io%2Fbackage%2Fdockur%2Fsamba%2Fsamba.json&query=%24.downloads&logo=github&style=flat&color=066da5&label=pulls
136 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: '0 0 * * *'
6 |
7 | concurrency:
8 | group: build
9 | cancel-in-progress: false
10 |
11 | jobs:
12 | shellcheck:
13 | name: Test
14 | uses: ./.github/workflows/check.yml
15 | build:
16 | name: Build
17 | needs: shellcheck
18 | runs-on: ubuntu-latest
19 | permissions:
20 | actions: write
21 | packages: write
22 | contents: read
23 | steps:
24 | -
25 | name: Get remote package data
26 | run: |
27 | set -e -o pipefail
28 | latest_tag=$(curl -sSf https://dl-cdn.alpinelinux.org/edge/main/aarch64/APKINDEX.tar.gz |
29 | tar -xzO APKINDEX |
30 | tr '\n' '\36' |
31 | sed -E 's/\o36{2,}/\n/g' |
32 | sed -nE '/(^|\o36)P:samba($|\o36)/ s/(^|.+\o36)V:([^\o36]+)($|\o36.+)/\2/ p')
33 | echo "Found tag: \"${latest_tag}\""
34 | latest_version="${latest_tag%-*}"
35 | major="${latest_version%%.*}"
36 | minor="${latest_version#*.}"
37 | minor="${minor%%.*}"
38 | echo "latest_tag=$latest_tag" >> $GITHUB_ENV
39 | echo "latest_version=$latest_version" >> $GITHUB_ENV
40 | echo "latest_minor=$major.$minor" >> $GITHUB_ENV
41 | echo "latest_major=$major" >> $GITHUB_ENV
42 | -
43 | name: Check if the tag exists locally
44 | uses: action-pack/tag-exists@v1
45 | id: checkTag
46 | with:
47 | tag: 'v${{ env.latest_tag }}'
48 | -
49 | name: Finish when found
50 | run: |
51 | val="${{ steps.checkTag.outputs.exists }}"
52 | echo "exists=${val}" >> $GITHUB_ENV
53 | -
54 | name: Checkout
55 | if: env.exists == 'false'
56 | uses: actions/checkout@v5
57 | with:
58 | fetch-depth: 0
59 | -
60 | name: Docker metadata
61 | id: meta
62 | if: env.exists == 'false'
63 | uses: docker/metadata-action@v5
64 | with:
65 | context: git
66 | images: |
67 | ${{ secrets.DOCKERHUB_REPO }}
68 | ghcr.io/${{ github.repository }}
69 | tags: |
70 | type=raw,value=latest,priority=100
71 | type=raw,value=${{ env.latest_major }},priority=450
72 | type=raw,value=${{ env.latest_minor }},priority=350
73 | type=raw,value=${{ env.latest_version }},priority=250
74 | labels: |
75 | org.opencontainers.image.title=${{ vars.NAME }}
76 | env:
77 | DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
78 | -
79 | name: Set up Docker Buildx
80 | if: env.exists == 'false'
81 | uses: docker/setup-buildx-action@v3
82 | -
83 | name: Login into Docker Hub
84 | if: env.exists == 'false'
85 | uses: docker/login-action@v3
86 | with:
87 | username: ${{ secrets.DOCKERHUB_USERNAME }}
88 | password: ${{ secrets.DOCKERHUB_TOKEN }}
89 | -
90 | name: Login to GitHub Container Registry
91 | if: env.exists == 'false'
92 | uses: docker/login-action@v3
93 | with:
94 | registry: ghcr.io
95 | username: ${{ github.actor }}
96 | password: ${{ secrets.GITHUB_TOKEN }}
97 | -
98 | name: Build Docker image
99 | if: env.exists == 'false'
100 | uses: docker/build-push-action@v6
101 | with:
102 | context: .
103 | push: true
104 | provenance: false
105 | platforms: linux/amd64,linux/arm64,linux/arm
106 | tags: ${{ steps.meta.outputs.tags }}
107 | labels: ${{ steps.meta.outputs.labels }}
108 | annotations: ${{ steps.meta.outputs.annotations }}
109 | build-args: |
110 | VERSION_ARG=${{ env.latest_version }}
111 | -
112 | name: Create a release
113 | if: env.exists == 'false'
114 | uses: action-pack/github-release@v2
115 | with:
116 | tag: "v${{ env.latest_tag }}"
117 | title: "v${{ env.latest_version }}"
118 | token: ${{ secrets.REPO_ACCESS_TOKEN }}
119 | -
120 | name: Send mail
121 | if: env.exists == 'false'
122 | uses: action-pack/send-mail@v1
123 | with:
124 | to: ${{secrets.MAILTO}}
125 | from: Github Actions <${{secrets.MAILTO}}>
126 | connection_url: ${{secrets.MAIL_CONNECTION}}
127 | subject: Build of ${{ github.event.repository.name }} v${{ env.latest_tag }} completed
128 | body: |
129 | The build job of ${{ github.event.repository.name }} v${{ env.latest_tag }} was completed successfully!
130 |
131 | See https://github.com/${{ github.repository }}/actions for more information.
132 |
--------------------------------------------------------------------------------
/samba.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -Eeuo pipefail
3 |
4 | # This function checks for the existence of a specified Samba user and group. If the user does not exist,
5 | # it creates a new user with the provided username, user ID (UID), group name, group ID (GID), and password.
6 | # If the user already exists, it updates the user's UID and group association as necessary,
7 | # and updates the password in the Samba database. The function ensures that the group also exists,
8 | # creating it if necessary, and modifies the group ID if it differs from the provided value.
9 | add_user() {
10 | local cfg="$1"
11 | local username="$2"
12 | local uid="$3"
13 | local groupname="$4"
14 | local gid="$5"
15 | local password="$6"
16 | local homedir="$7"
17 |
18 | # Check if the smb group exists, if not, create it
19 | if ! getent group "$groupname" &>/dev/null; then
20 | [[ "$groupname" != "smb" ]] && echo "Group $groupname does not exist, creating group..."
21 | groupadd -o -g "$gid" "$groupname" > /dev/null || { echo "Failed to create group $groupname"; return 1; }
22 | else
23 | # Check if the gid right,if not, change it
24 | local current_gid
25 | current_gid=$(getent group "$groupname" | cut -d: -f3)
26 | if [[ "$current_gid" != "$gid" ]]; then
27 | [[ "$groupname" != "smb" ]] && echo "Group $groupname exists but GID differs, updating GID..."
28 | groupmod -o -g "$gid" "$groupname" > /dev/null || { echo "Failed to update GID for group $groupname"; return 1; }
29 | fi
30 | fi
31 |
32 | # Check if the user already exists, if not, create it
33 | if ! id "$username" &>/dev/null; then
34 | [[ "$username" != "$USER" ]] && echo "User $username does not exist, creating user..."
35 | extra_args=()
36 | # Check if home directory already exists, if so do not create home during user creation
37 | if [ -d "$homedir" ]; then
38 | extra_args=("${extra_args[@]}" -H)
39 | fi
40 | adduser "${extra_args[@]}" -S -D -h "$homedir" -s /sbin/nologin -G "$groupname" -u "$uid" -g "Samba User" "$username" || { echo "Failed to create user $username"; return 1; }
41 | else
42 | # Check if the uid right,if not, change it
43 | local current_uid
44 | current_uid=$(id -u "$username")
45 | if [[ "$current_uid" != "$uid" ]]; then
46 | echo "User $username exists but UID differs, updating UID..."
47 | usermod -o -u "$uid" "$username" > /dev/null || { echo "Failed to update UID for user $username"; return 1; }
48 | fi
49 |
50 | # Update user's group
51 | usermod -g "$groupname" "$username" > /dev/null || { echo "Failed to update group for user $username"; return 1; }
52 | fi
53 |
54 | # Check if the user is a samba user
55 | pdb_output=$(pdbedit -s "$cfg" -L) #Do not combine the two commands into one, as this could lead to issues with the execution order and proper passing of variables.
56 | if echo "$pdb_output" | grep -q "^$username:"; then
57 | # skip samba password update if password is * or !
58 | if [[ "$password" != "*" && "$password" != "!" ]]; then
59 | # If the user is a samba user, update its password in case it changed
60 | echo -e "$password\n$password" | smbpasswd -c "$cfg" -s "$username" > /dev/null || { echo "Failed to update Samba password for $username"; return 1; }
61 | fi
62 | else
63 | # If the user is not a samba user, create it and set a password
64 | echo -e "$password\n$password" | smbpasswd -a -c "$cfg" -s "$username" > /dev/null || { echo "Failed to add Samba user $username"; return 1; }
65 | [[ "$username" != "$USER" ]] && echo "User $username has been added to Samba and password set."
66 | fi
67 |
68 | return 0
69 | }
70 |
71 | # Set variables for group and share directory
72 | group="smb"
73 | share="/storage"
74 | secret="/run/secrets/pass"
75 | config="/etc/samba/smb.conf"
76 | users="/etc/samba/users.conf"
77 |
78 | # Create shared directory
79 | mkdir -p "$share" || { echo "Failed to create directory $share"; exit 1; }
80 |
81 | # Check if the secret file exists and if its size is greater than zero
82 | if [ -s "$secret" ]; then
83 | PASS=$(cat "$secret")
84 | fi
85 |
86 | # Check if config file is not a directory
87 | if [ -d "$config" ]; then
88 |
89 | echo "The bind $config maps to a file that does not exist!"
90 | exit 1
91 |
92 | fi
93 |
94 | # Check if an external config file was supplied
95 | if [ -f "$config" ] && [ -s "$config" ]; then
96 |
97 | # Inform the user we are using a custom configuration file.
98 | echo "Using provided configuration file: $config."
99 |
100 | else
101 |
102 | config="/etc/samba/smb.tmp"
103 | template="/etc/samba/smb.default"
104 |
105 | if [ ! -f "$template" ]; then
106 | echo "Your /etc/samba directory does not contain a valid smb.conf file!"
107 | exit 1
108 | fi
109 |
110 | # Generate a config file from template
111 | rm -f "$config"
112 | cp "$template" "$config"
113 |
114 | # Set custom display name if provided
115 | if [ -n "$NAME" ] && [[ "${NAME,,}" != "data" ]]; then
116 | sed -i "s/\[Data\]/\[$NAME\]/" "$config"
117 | fi
118 |
119 | # Update force user and force group in smb.conf
120 | sed -i "s/^\(\s*\)force user =.*/\1force user = $USER/" "$config"
121 | sed -i "s/^\(\s*\)force group =.*/\1force group = $group/" "$config"
122 |
123 | # Verify if the RW variable is equal to false (indicating read-only mode)
124 | if [[ "$RW" == [Ff0]* ]]; then
125 | # Adjust settings in smb.conf to set share to read-only
126 | sed -i "s/^\(\s*\)writable =.*/\1writable = no/" "$config"
127 | sed -i "s/^\(\s*\)read only =.*/\1read only = yes/" "$config"
128 | fi
129 |
130 | fi
131 |
132 | # Check if users file is not a directory
133 | if [ -d "$users" ]; then
134 |
135 | echo "The file $users does not exist, please check that you mapped it to a valid path!"
136 | exit 1
137 |
138 | fi
139 |
140 | # Create directories if missing
141 | mkdir -p /var/lib/samba/sysvol
142 | mkdir -p /var/lib/samba/private
143 | mkdir -p /var/lib/samba/bind-dns
144 |
145 | # Check if multi-user mode is enabled
146 | if [ -f "$users" ] && [ -s "$users" ]; then
147 |
148 | while IFS= read -r line || [[ -n ${line} ]]; do
149 |
150 | # Skip lines that are comments or empty
151 | [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
152 |
153 | # Split each line by colon and assign to variables
154 | IFS=':' read -r username uid groupname gid password homedir <<< "$line"
155 |
156 | # Check if all required fields are present
157 | if [[ -z "$username" || -z "$uid" || -z "$groupname" || -z "$gid" || -z "$password" ]]; then
158 | echo "Skipping incomplete line: $line"
159 | continue
160 | fi
161 |
162 | # Default homedir if not explicitly set for user
163 | [[ -z "$homedir" ]] && homedir="$share"
164 |
165 | # Call the function with extracted values
166 | add_user "$config" "$username" "$uid" "$groupname" "$gid" "$password" "$homedir" || { echo "Failed to add user $username"; exit 1; }
167 |
168 | done < <(tr -d '\r' < "$users")
169 |
170 | else
171 |
172 | add_user "$config" "$USER" "$UID" "$group" "$GID" "$PASS" "$share" || { echo "Failed to add user $USER"; exit 1; }
173 |
174 | if [[ "$RW" != [Ff0]* ]]; then
175 | # Set permissions for share directory if new (empty), leave untouched if otherwise
176 | if [ -z "$(ls -A "$share")" ]; then
177 | chmod 0770 "$share" || { echo "Failed to set permissions for directory $share"; exit 1; }
178 | chown "$USER:$group" "$share" || { echo "Failed to set ownership for directory $share"; exit 1; }
179 | fi
180 | fi
181 |
182 | fi
183 |
184 | # Store configuration location for Healthcheck
185 | ln -sf "$config" /etc/samba.conf
186 |
187 | # Set directory permissions
188 | [ -d /run/samba/msg.lock ] && chmod -R 0755 /run/samba/msg.lock
189 | [ -d /var/log/samba/cores ] && chmod -R 0700 /var/log/samba/cores
190 | [ -d /var/cache/samba/msg.lock ] && chmod -R 0755 /var/cache/samba/msg.lock
191 |
192 | # Start the Samba daemon with the following options:
193 | # --configfile: Location of the configuration file.
194 | # --foreground: Run in the foreground instead of daemonizing.
195 | # --debug-stdout: Send debug output to stdout.
196 | # --debuglevel=1: Set debug verbosity level to 1.
197 | # --no-process-group: Don't create a new process group for the daemon.
198 | exec smbd --configfile="$config" --foreground --debug-stdout -d "${DEBUG_LEVEL:-1}" --no-process-group
199 |
--------------------------------------------------------------------------------