diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f4f183130 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# macOS +._* +.DS_Store +.AppleDouble + +.Spotlight-V100 +.Trashes +.fseventsd + +.AppleDB +.AppleDesktop diff --git a/samba/CHANGELOG.md b/samba/CHANGELOG.md index b111409c9..422632027 100644 --- a/samba/CHANGELOG.md +++ b/samba/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 12.6.1 + +- Add `mdnsd` for macOS discoverability +- Rename `smb.conf` Go template for disambiguation with new templates +- Add config option, and `nmbd` startup logic, to disable NetBIOS +- Add config options, and startup logic, to override default ports (445/139) +- Colocate mapped mounts to a `/smbshare` prefix to avoid potential confusion +- Update `config.yaml` `map:` to new object syntax +- Refactor `smb.conf` to use Go template iterators + ## 12.6.0 - Do initial healthcheck after 3s to speedup startup diff --git a/samba/DOCS.md b/samba/DOCS.md index 0ed6bfffc..65e0d27e1 100644 --- a/samba/DOCS.md +++ b/samba/DOCS.md @@ -8,6 +8,8 @@ Follow these steps to get the app (formerly known as add-on) installed on your s 2. Find the "Samba share" app and click it. 3. Click on the "INSTALL" button. +[![Open your Home Assistant instance and show the dashboard of an app.](https://my.home-assistant.io/badges/supervisor_addon.svg)](https://my.home-assistant.io/redirect/supervisor_addon/?addon=core_samba) + ## How to use 1. In the configuration section, set a username and password. @@ -35,39 +37,39 @@ Directory | Description App configuration: ```yaml -workgroup: WORKGROUP -local_master: true -username: homeassistant -password: YOUR_PASSWORD -enabled_shares: - - addons - - addon_configs - - backup - - config - - media - - share - - ssl -allow_hosts: - - 10.0.0.0/8 - - 172.16.0.0/12 - - 192.168.0.0/16 - - 169.254.0.0/16 - - fe80::/10 - - fc00::/7 -veto_files: - - "._*" - - ".DS_Store" - - Thumbs.db -compatibility_mode: false + username: homeassistant + password: null + workgroup: WORKGROUP + enabled_shares: + - addons + - addon_configs + - backup + - config + - media + - share + - ssl + local_master: true + compatibility_mode: false + apple_compatibility_mode: true + server_signing: "default" + netbios: true + veto_files: + - ._* + - .DS_Store + - Thumbs.db + - icon? + - .Trashes + allow_hosts: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + - 169.254.0.0/16 + - fe80::/10 + - fc00::/7 ``` -### Option: `workgroup` (required) -Change WORKGROUP to reflect your network needs. - -### Option: `local_master` (required) -Enable to try and become a local master browser on a subnet. ### Option: `username` (required) @@ -77,19 +79,17 @@ The username you would like to use to authenticate with the Samba server. The password that goes with the username configured for authentication. -### Option: `enabled_shares` (required) +### Option: `workgroup` (required) -List of Samba shares that will be accessible. Any shares removed or commented out of the list will not be accessible. +Change WORKGROUP to reflect your network needs. -### Option: `allow_hosts` (required) +### Option: `enabled_shares` (required) -List of hosts/networks allowed to access the shared folders. +List of Samba shares that will be accessible. Any shares removed or commented out of the list will not be accessible. -### Option: `veto_files` (optional) +### Option: `local_master` (required) -List of files that are neither visible nor accessible. Useful to stop clients -from littering the share with temporary hidden files -(e.g., macOS `.DS_Store` or Windows `Thumbs.db` files) +Enable to try and become a local master browser on a subnet. ### Option: `compatibility_mode` @@ -114,6 +114,31 @@ Refer to the man page for smb.conf for detailed information about the values: ** Defaults to `default`. +### Option: `netbios` + +NetBIOS is a legacy network protocol for accessing SMB/CIFS shares. +Enable for legacy clients older than Windows Vista (Windows 95/98/ME, Windows NT, Windows 2000, Windows XP and LanManager), or OS X 10.9 (Mavericks). This setting is enabled by default for compatibility; disable it on modern installations. + +Defaults to `true`. + +### Option: `veto_files` (optional) + +List of files that are neither visible nor accessible. Useful to stop clients +from littering the share with temporary hidden files +(e.g., macOS `.DS_Store` or Windows `Thumbs.db` files) + +### Option: `allow_hosts` (required) + +List of hosts/networks allowed to access the shared folders. + +## Network ports + +From version 12.6.1 of this app, it is possible to override the default ports in the app configuration. Only very specific use cases should do this. +If ports have been changed, due to known constraints with macOS Finder, it is **not** possible to access the share from Finder's Network location browser. You _can_ access the share by opening the **Connect to server...** dialog (⌘ + K). +```URL +smb://:/ +``` + ## Support Got questions? diff --git a/samba/Dockerfile b/samba/Dockerfile index c8d070f33..81e1dcd73 100644 --- a/samba/Dockerfile +++ b/samba/Dockerfile @@ -6,8 +6,11 @@ ENV LANG C.UTF-8 # Setup base RUN \ - apk add --no-cache samba \ - && mkdir -p /var/lib/samba \ + echo '@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing' >> \ + /etc/apk/repositories && \ + apk add --no-cache samba mdnsd@testing=0.12-r1 \ + && rm -f /etc/mdns.d/* \ + && mkdir -p /var/lib/samba /smbshare \ && touch \ /etc/samba/lmhosts \ /var/lib/samba/account_policy.tdb \ diff --git a/samba/config.yaml b/samba/config.yaml index a4a027352..374678288 100644 --- a/samba/config.yaml +++ b/samba/config.yaml @@ -1,5 +1,5 @@ --- -version: 12.6.0 +version: 12.6.1 slug: samba name: Samba share description: Expose Home Assistant folders with SMB/CIFS @@ -12,18 +12,31 @@ host_network: true image: homeassistant/{arch}-addon-samba init: false map: - - addons:rw - - all_addon_configs:rw - - backup:rw - - homeassistant_config:rw - - media:rw - - share:rw - - ssl:rw + - type: addons + read_only: false + path: "/smbshare/addons" + - type: all_addon_configs + read_only: false + path: "/smbshare/addon_configs" + - type: backup + read_only: false + path: "/smbshare/backup" + - type: homeassistant_config + read_only: false + path: "/smbshare/homeassistant" + - type: media + read_only: false + path: "/smbshare/media" + - type: share + read_only: false + path: "/smbshare/share" + - type: ssl + read_only: false + path: "/smbshare/ssl" options: username: homeassistant password: null workgroup: WORKGROUP - local_master: true enabled_shares: - addons - addon_configs @@ -32,9 +45,11 @@ options: - media - share - ssl + local_master: true compatibility_mode: false apple_compatibility_mode: true server_signing: "default" + netbios: true veto_files: - ._* - .DS_Store @@ -52,14 +67,21 @@ schema: username: str password: password workgroup: str - local_master: bool enabled_shares: - "match(^(?i:(addons|addon_configs|backup|config|media|share|ssl))$)" + local_master: bool compatibility_mode: bool apple_compatibility_mode: bool server_signing: list(default|auto|mandatory|disabled) + netbios: bool veto_files: - str allow_hosts: - str startup: services +ports: + 445/tcp: null + 139/tcp: null +ports_description: + 445/tcp: SMB over IP + 139/tcp: SMB over NetBIOS \ No newline at end of file diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run index bd94a670a..5e1c871ad 100755 --- a/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/init-smbd/run @@ -38,11 +38,17 @@ bashio::log.info "Interfaces: $(printf '%s ' "${interfaces[@]}")" # Generate Samba configuration. jq ".interfaces = $(jq -c -n '$ARGS.positional' --args -- "${interfaces[@]}") | - .enabled_shares.[] |= ascii_downcase" /data/options.json \ + .enabled_shares.[] |= ascii_downcase | + .ports = $(bashio::addon.network)" /data/options.json \ | tempio \ - -template /usr/share/tempio/smb.gtpl \ + -template /usr/share/tempio/smb.conf.gtpl \ -out /etc/samba/smb.conf +tempio \ + -conf /data/options.json \ + -template /usr/share/tempio/smb.conf.inc.gtpl \ + -out /etc/samba/smb.conf.inc + # Init user username=$(bashio::config 'username') password=$(bashio::config 'password') diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/dependencies.d/smbd b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/dependencies.d/smbd new file mode 100644 index 000000000..e69de29bb diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/run new file mode 100755 index 000000000..b5849656c --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/run @@ -0,0 +1,40 @@ +#!/command/with-contenv bashio +# vim: ft=bash +# shellcheck shell=bash + + +if bashio::var.true "$(bashio::addon.host_network)"; then + bashio::log.info "Host network detected. Configuring mDNS" + + # Read hostname from API or setting default "hassio" + HOSTNAME=$(bashio::info.hostname) + if bashio::var.is_empty "${HOSTNAME}"; then + bashio::log.warning "Can't read hostname, using default." + HOSTNAME="hassio" + fi + + declare -r smbfile="/etc/mdns.d/smb.service" + declare -r adiskfile="/etc/mdns.d/adisk.service" + declare -r _TMP="$(mktemp -d -t mdnsd.XXXXXX)" + rm -f -v "${smbfile}" "${adiskfile}" + + # Generate JSON configuration for tempio + jq -c " + .ports = $(bashio::addon.network) + | .sambaversion = \"$(smbstatus --version | cut -d '[ \t]+' -F 2)\" + " /data/options.json > "${_TMP}/options.json" + + # Generate _smb._tcp service advertisement + tempio \ + -conf "${_TMP}/options.json" \ + -template /usr/share/tempio/smb.service.gtpl \ + -out ${smbfile} + + # Generate _adisk._tcp service advertisement + tempio \ + -conf "${_TMP}/options.json" \ + -template /usr/share/tempio/adisk.service.gtpl \ + -out ${adiskfile} + + builtin exec $(which mdnsd) -n -i $(bashio::network.name) +fi diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/type b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/type new file mode 100644 index 000000000..5883cff0c --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/type @@ -0,0 +1 @@ +longrun diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/up b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/up new file mode 100644 index 000000000..31b0a0205 --- /dev/null +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/mdnsd/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/discovery/run \ No newline at end of file diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run index 74bb858e8..6703ec48d 100755 --- a/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/nmbd/run @@ -4,7 +4,12 @@ # ============================================================================== # Start nmbd service # ============================================================================== -exec nmbd \ + +if ! bashio::config.true 'netbios'; then + builtin exec sleep infinity +fi + +builtin exec nmbd \ --foreground \ --debug-stdout \ --no-process-group diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run index 219d3d4eb..7ea104481 100755 --- a/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run +++ b/samba/rootfs/etc/s6-overlay/s6-rc.d/smbd/run @@ -4,7 +4,7 @@ # ============================================================================== # Start smbd service # ============================================================================== -exec smbd \ +builtin exec smbd \ --foreground \ --debug-stdout \ --no-process-group diff --git a/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdnsd b/samba/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/mdnsd new file mode 100644 index 000000000..e69de29bb diff --git a/samba/rootfs/usr/share/tempio/adisk.service.gtpl b/samba/rootfs/usr/share/tempio/adisk.service.gtpl new file mode 100644 index 000000000..97cd6350a --- /dev/null +++ b/samba/rootfs/usr/share/tempio/adisk.service.gtpl @@ -0,0 +1,10 @@ +# /etc/mdns.d/adisk.service -- mDNS-SD _adisk._tcp for macOS Finder +# macOS uses _adisk._tcp TXT records to discover SMB shares and honours +# the port from the companion _smb._tcp SRV record. +name {{ env "HOSTNAME" }} +type _adisk._tcp +port 9 +txt sys=adVF=0x100 +{{ range $i, $share := .enabled_shares -}} +txt dk{{ $i }}=adVN={{ $share }},adVF=0x80 +{{ end -}} \ No newline at end of file diff --git a/samba/rootfs/usr/share/tempio/smb.conf.gtpl b/samba/rootfs/usr/share/tempio/smb.conf.gtpl new file mode 100644 index 000000000..33fc34cf2 --- /dev/null +++ b/samba/rootfs/usr/share/tempio/smb.conf.gtpl @@ -0,0 +1,56 @@ +[global] + netbios name = {{ env "HOSTNAME" }} + dns hostname = {{ env "HOSTNAME" }}.local + additional dns hostnames = {{ env "HOSTNAME" }}._smb._tcp.local + workgroup = {{ .workgroup }} + server string = Samba Home Assistant + local master = {{ .local_master | ternary "yes" "no" }} + preferred master = {{ .local_master | ternary "yes" "auto" }} + server role = standalone + {{ $smb_port := default 445 (index .ports "445/tcp") -}} + {{ $nbt_port := default 139 (index .ports "139/tcp") -}} + smb ports = {{ cat $smb_port (ternary $nbt_port nil .netbios) }} + + security = user + idmap config * : backend = tdb + idmap config * : range = 1000000-2000000 + + load printers = no + disable spoolss = yes + {{ if .netbios -}} + server services = smb nbt + {{ else -}} + disable netbios = yes + server services = smb + {{ end -}} + dns proxy = no + + log level = 1 + + bind interfaces only = yes + interfaces = lo {{ .interfaces | join " " }} + hosts allow = 127.0.0.1 {{ .allow_hosts | join " " }} + + {{ if .compatibility_mode -}} + client min protocol = NT1 + server min protocol = NT1 + lanman auth = yes + ntlm auth = yes + {{ end -}} + + mangled names = no + dos charset = CP850 + unix charset = UTF-8 + + {{ if .apple_compatibility_mode -}} + vfs objects = catia fruit streams_xattr + {{ end -}} + + server signing = {{ .server_signing }} + allow dns updates = disabled + +{{ range $i, $share := .enabled_shares -}} +[{{ $share }}] + path = /smbshare/{{ ternary "homeassistant" $share ( eq $share "config" ) }} + include = /etc/samba/smb.conf.inc +{{ end -}} diff --git a/samba/rootfs/usr/share/tempio/smb.conf.inc.gtpl b/samba/rootfs/usr/share/tempio/smb.conf.inc.gtpl new file mode 100644 index 000000000..d1331bd85 --- /dev/null +++ b/samba/rootfs/usr/share/tempio/smb.conf.inc.gtpl @@ -0,0 +1,8 @@ + browseable = yes + writeable = yes + + valid users = {{ .username }} + force user = root + force group = root + veto files = /{{ .veto_files | join "/" }}/ + delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} diff --git a/samba/rootfs/usr/share/tempio/smb.gtpl b/samba/rootfs/usr/share/tempio/smb.gtpl deleted file mode 100644 index 6b00b14c3..000000000 --- a/samba/rootfs/usr/share/tempio/smb.gtpl +++ /dev/null @@ -1,125 +0,0 @@ -[global] - netbios name = {{ env "HOSTNAME" }} - workgroup = {{ .workgroup }} - server string = Samba Home Assistant - local master = {{ .local_master | ternary "yes" "no" }} - - security = user - ntlm auth = yes - idmap config * : backend = tdb - idmap config * : range = 1000000-2000000 - - load printers = no - disable spoolss = yes - - log level = 1 - - bind interfaces only = yes - interfaces = lo {{ .interfaces | join " " }} - hosts allow = 127.0.0.1 {{ .allow_hosts | join " " }} - - {{ if .compatibility_mode }} - client min protocol = NT1 - server min protocol = NT1 - {{ end }} - - mangled names = no - dos charset = CP850 - unix charset = UTF-8 - - {{ if .apple_compatibility_mode }} - vfs objects = catia fruit streams_xattr - {{ end }} - - server signing = {{ .server_signing }} - -{{ if (has "config" .enabled_shares) }} -[config] - browseable = yes - writeable = yes - path = /homeassistant - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "addons" .enabled_shares) }} -[addons] - browseable = yes - writeable = yes - path = /addons - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "addon_configs" .enabled_shares) }} -[addon_configs] - browseable = yes - writeable = yes - path = /addon_configs - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "ssl" .enabled_shares) }} -[ssl] - browseable = yes - writeable = yes - path = /ssl - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "share" .enabled_shares) }} -[share] - browseable = yes - writeable = yes - path = /share - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "backup" .enabled_shares) }} -[backup] - browseable = yes - writeable = yes - path = /backup - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} - -{{ if (has "media" .enabled_shares) }} -[media] - browseable = yes - writeable = yes - path = /media - - valid users = {{ .username }} - force user = root - force group = root - veto files = /{{ .veto_files | join "/" }}/ - delete veto files = {{ eq (len .veto_files) 0 | ternary "no" "yes" }} -{{ end }} diff --git a/samba/rootfs/usr/share/tempio/smb.service.gtpl b/samba/rootfs/usr/share/tempio/smb.service.gtpl new file mode 100644 index 000000000..e4641b121 --- /dev/null +++ b/samba/rootfs/usr/share/tempio/smb.service.gtpl @@ -0,0 +1,17 @@ +# /etc/mdns.d/smb.service -- mDNS-SD advertisement of SMB service +type _smb._tcp +name {{ env "HOSTNAME" }} +{{ $smb_port := default (index .ports "139/tcp") (index .ports "445/tcp") | default 445 -}} +port {{ $smb_port }} +txt s=samba +txt v={{ .sambaversion }} + +### Seems to be a bug in mdnsd when setting target or cname +# target ha.local +# cname smb.ha.local + +txt adVF=0x82 +txt adVN=Home Assistant +{{ range $i, $share := .enabled_shares -}} +txt dk{{ $i }}={{ $share }} +{{ end -}} \ No newline at end of file diff --git a/samba/translations/en.yaml b/samba/translations/en.yaml index 7fee4e38d..736e8c1c5 100644 --- a/samba/translations/en.yaml +++ b/samba/translations/en.yaml @@ -39,6 +39,12 @@ configuration: Configure SMB server message signing requirements. Refer to the smb.conf man page for more information. Only change this if you know your SMB clients can support it. + netbios: + name: Enable NetBIOS over IP + description: >- + Enable NetBIOS over IP for legacy SMB clients + (Windows 95/98/ME, Windows NT, Windows 2000, Windows XP and LanManager clients). + Disable to improve security and performance if you do not have legacy SMB clients. veto_files: name: Veto Files description: List of files that are neither visible nor accessible.