├── .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 | [![Stars](https://starchart.cc/dockur/samba.svg?variant=adaptive)](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 | --------------------------------------------------------------------------------