├── .dockerignore
├── .github
├── dependabot.yml
├── logo.png
├── renovate.json
└── workflows
│ ├── build.yml
│ ├── check.yml
│ ├── hub.yml
│ └── test.yml
├── .gitignore
├── Dockerfile
├── compose.yml
├── license.md
├── readme.md
├── samba.sh
├── smb.conf
└── users.conf
/.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/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dockur/samba/6613c4ea4d6fffb9ca0b11e3cbeac4979b3163cd/.github/logo.png
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": ["config:recommended", ":disableDependencyDashboard"],
4 | "forkProcessing": "enabled"
5 | }
6 |
--------------------------------------------------------------------------------
/.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 | #!/bin/bash
28 | package="edge/main/aarch64/samba"
29 | resp=$(curl -sS "https://pkgs.alpinelinux.org/package/$package")
30 | latest_tag=$(echo "$resp" | grep -A 3 -i \>version\< | sed -e 's/<[^>]*>//g' | sed -E 's#.*>([0-9\.]+)-r[0-9]+#\1#g' | tail -1 | sed 's/^[ \t]*//;s/[ \t]*$//')
31 | [ -z "$latest_tag" ] && echo "Tag not found!" && exit 1
32 | [[ "$latest_tag" = v* ]] && latest_tag="${latest_tag:1}"
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 | -
42 | name: Check if the tag exists locally
43 | uses: action-pack/tag-exists@v1
44 | id: checkTag
45 | with:
46 | tag: 'v${{ env.latest_tag }}'
47 | -
48 | name: Finish when found
49 | run: |
50 | #!/bin/bash
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@v4
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_minor }}
72 | type=raw,value=${{ env.latest_version }},priority=250
73 | labels: |
74 | org.opencontainers.image.title=${{ vars.NAME }}
75 | env:
76 | DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
77 | -
78 | name: Set up Docker Buildx
79 | if: env.exists == 'false'
80 | uses: docker/setup-buildx-action@v3
81 | -
82 | name: Login into Docker Hub
83 | if: env.exists == 'false'
84 | uses: docker/login-action@v3
85 | with:
86 | username: ${{ secrets.DOCKERHUB_USERNAME }}
87 | password: ${{ secrets.DOCKERHUB_TOKEN }}
88 | -
89 | name: Login to GitHub Container Registry
90 | if: env.exists == 'false'
91 | uses: docker/login-action@v3
92 | with:
93 | registry: ghcr.io
94 | username: ${{ github.actor }}
95 | password: ${{ secrets.GITHUB_TOKEN }}
96 | -
97 | name: Build Docker image
98 | if: env.exists == 'false'
99 | uses: docker/build-push-action@v6
100 | with:
101 | context: .
102 | push: true
103 | provenance: false
104 | platforms: linux/amd64,linux/arm64,linux/arm
105 | tags: ${{ steps.meta.outputs.tags }}
106 | labels: ${{ steps.meta.outputs.labels }}
107 | annotations: ${{ steps.meta.outputs.annotations }}
108 | build-args: |
109 | VERSION_ARG=${{ env.latest_version }}
110 | -
111 | name: Create a release
112 | if: env.exists == 'false'
113 | uses: action-pack/github-release@v2
114 | with:
115 | tag: "v${{ env.latest_tag }}"
116 | title: "v${{ env.latest_version }}"
117 | token: ${{ secrets.REPO_ACCESS_TOKEN }}
118 | -
119 | name: Send mail
120 | if: env.exists == 'false'
121 | uses: action-pack/send-mail@v1
122 | with:
123 | to: ${{secrets.MAILTO}}
124 | from: Github Actions <${{secrets.MAILTO}}>
125 | connection_url: ${{secrets.MAIL_CONNECTION}}
126 | subject: Build of ${{ github.event.repository.name }} v${{ env.latest_tag }} completed
127 | body: |
128 | The build job of ${{ github.event.repository.name }} v${{ env.latest_tag }} was completed successfully!
129 |
130 | See https://github.com/${{ github.repository }}/actions for more information.
131 |
--------------------------------------------------------------------------------
/.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@v4
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.1.0
17 | with:
18 | dockerfile: Dockerfile
19 | ignore: DL3018
20 | failure-threshold: warning
21 |
--------------------------------------------------------------------------------
/.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@v4
15 | -
16 | name: Docker Hub Description
17 | uses: peter-evans/dockerhub-description@v4
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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:edge
2 |
3 | RUN set -eu && \
4 | apk --no-cache add \
5 | tini \
6 | bash \
7 | samba \
8 | tzdata \
9 | shadow && \
10 | addgroup -S smb && \
11 | rm -f /etc/samba/smb.conf && \
12 | rm -rf /tmp/* /var/cache/apk/*
13 |
14 | COPY --chmod=755 samba.sh /usr/bin/samba.sh
15 | COPY --chmod=664 smb.conf /etc/samba/smb.default
16 |
17 | VOLUME /storage
18 | EXPOSE 139 445
19 |
20 | ENV NAME="Data"
21 | ENV USER="samba"
22 | ENV PASS="secret"
23 |
24 | ENV UID=1000
25 | ENV GID=1000
26 | ENV RW=true
27 |
28 | HEALTHCHECK --interval=60s --timeout=15s CMD smbclient --configfile=/etc/samba.conf -L \\localhost -U % -m SMB3
29 |
30 | ENTRYPOINT ["/sbin/tini", "--", "/usr/bin/samba.sh"]
31 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 "USER=samba" -e "PASS=secret" -v "${PWD:-.}/samba:/storage" 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 |
--------------------------------------------------------------------------------
/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 --debuglevel=1 --no-process-group
199 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/users.conf:
--------------------------------------------------------------------------------
1 | #username:UID:groupname:GID:password:homedir
2 | samba:1000:smb:1000:secret
3 |
--------------------------------------------------------------------------------