Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Samba version #58

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
92 changes: 22 additions & 70 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,88 +1,40 @@
FROM alpine:latest
LABEL maintainer="Óscar de Arriba <[email protected]>"

ARG BUILD_DATE

LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.name="TimeMachine - Samba" \
org.label-schema.description="TimeMachine server using Samba protocol." \
org.label-schema.vcs-url="https://github.com/odarriba/docker-timemachine" \
org.label-schema.schema-version="1.0"

##################
## BUILDING ##
##################

# Versions to use
ENV netatalk_version 3.1.12

WORKDIR /

# Prerequisites
RUN apk update && \
apk upgrade && \
apk add --no-cache \
bash \
curl \
libldap \
libgcrypt \
python \
dbus \
dbus-glib \
py-dbus \
linux-pam \
cracklib \
db \
libevent \
file \
tzdata \
acl \
openssl \
supervisor && \
apk add --no-cache --virtual .build-deps \
build-base \
autoconf \
automake \
libtool \
libgcrypt-dev \
linux-pam-dev \
cracklib-dev \
acl-dev \
db-dev \
dbus-dev \
libevent-dev && \
ln -s -f /bin/true /usr/bin/chfn && \
cd /tmp && \
curl -o netatalk-${netatalk_version}.tar.gz -L https://downloads.sourceforge.net/project/netatalk/netatalk/${netatalk_version}/netatalk-${netatalk_version}.tar.gz && \
tar xvf netatalk-${netatalk_version}.tar.gz && \
cd netatalk-${netatalk_version} && \
CFLAGS="-Wno-unused-result -O2" ./configure \
--prefix=/usr \
--localstatedir=/var/state \
--sysconfdir=/etc \
--with-dbus-sysconf-dir=/etc/dbus-1/system.d/ \
--with-init-style=debian-sysv \
--sbindir=/usr/bin \
--enable-quota \
--with-tdb \
--enable-silent-rules \
--with-cracklib \
--with-cnid-cdb-backend \
--enable-pgp-uam \
--with-acls && \
make && \
make install && \
cd /tmp && \
rm -rf netatalk-${netatalk_version} netatalk-${netatalk_version}.tar.gz && \
apk del .build-deps
apk upgrade && \
apk add --no-cache \
bash \
samba-server \
samba-common-tools \
samba-winbind \
supervisor

RUN mkdir -p /timemachine && \
mkdir -p /var/log/supervisor && \
mkdir -p /conf.d/netatalk

# Create the log file
RUN touch /var/log/afpd.log
mkdir -p /etc/samba && \
mkdir -p /var/log/supervisor

ADD entrypoint.sh /entrypoint.sh
ADD bin/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ADD start_netatalk.sh /start_netatalk.sh
ADD bin/add-account /usr/bin/add-account
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf
ADD afp.conf /etc/afp.conf
ADD config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
ADD config/smb.conf /etc/samba/smb.conf
ADD config/com.apple.TimeMachine.quota.plist /com.apple.TimeMachine.quota.plist

EXPOSE 548 636
EXPOSE 137/UDP 138/UDP 139/TCP 445/TCP

VOLUME ["/timemachine"]

Expand Down
90 changes: 58 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
# docker-timemachine
A docker container to compile the lastest version of Netatalk in order to run a Time Machine server.
A docker container to run a Time Machine server using SMB.

**Note:** This image is now using Samba as the network protocol. There is a AFP container available to use with old OSX versions. Check README in `afp` branch for more information.

**Coming from AFP?** We have an [upgrade guide](UPGRADE.md) to have you covered.

## Running on ARM / RPi
If you want to use this on an ARM-Device (like the Raspberry Pi), you have two options:

- Get the precompiled image (latest compilation on 29-03-2018):
```
$ docker run -h timemachine --name timemachine --restart=unless-stopped -d -v /external_volume:/timemachine -it -p 548:548 -p 636:636 odarriba/timemachine-rpi
```
- Build the image directly on your device:
```
$ docker build -t timemachine-rpi:latest -f Dockerfile .
$ docker run -h timemachine --name timemachine --restart=unless-stopped -d -v /external_volume:/timemachine -it -p 548:548 -p 636:636 timemachine-rpi
```
If you want to use this on an ARM-Device (like the Raspberry Pi), you have to compile it first:

```
$ docker build -t timemachine-rpi:latest -f Dockerfile .

$ docker run -h timemachine \
--name timemachine \
--restart=unless-stopped \
-dit \
-v /external_volume:/timemachine \
-p 137:137/udp \
-p 138:138/udp \
-p 139:139/tcp \
-p 445:445/tcp \
timemachine-rpi
```

## Installation

Expand All @@ -21,7 +30,17 @@ If you want to use this on an ARM-Device (like the Raspberry Pi), you have two o
To download the docker container and execute it, simply run:

```
$ docker run -h timemachine --name timemachine --restart=unless-stopped -d -v /external_volume:/timemachine -it -p 548:548 -p 636:636 --ulimit nofile=65536:65536 odarriba/timemachine
$ docker run -h timemachine \
--name timemachine \
--restart=unless-stopped \
-dit \
-v /external_volume:/timemachine \
-p 137:137/udp \
-p 138:138/udp \
-p 139:139/tcp \
-p 445:445/tcp \
--ulimit nofile=65536:65536 \
odarriba/timemachine
```

Replace `external_volume` with a local path where you want to store your data.
Expand All @@ -35,21 +54,19 @@ As the image has been started using the `--restart=always` flag, it will start w
To add a user, run:

```
$ docker exec timemachine add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [VOL_SIZE_MB]
$ docker exec timemachine add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [TM_SIZE_MB]
```

Or, if you want to add a user with a specific UID/GID, use the following format

```
$ docker exec timemachine add-account -i 1000 -g 1000 USERNAME PASSWORD VOL_NAME VOL_ROOT [VOL_SIZE_MB]
$ docker exec timemachine add-account -i 1000 -g 1000 USERNAME PASSWORD VOL_NAME VOL_ROOT [TM_SIZE_MB]
```

But take care that:
* `VOL_NAME` will be the name of the volume shown on your OSX as the network drive
* `VOL_ROOT` should be an absolute path, preferably a sub-path of `/timemachine` (e.g., `/timemachine/backup`), so it will be stored in the according sub-path of your external volume.
* `VOL_SIZE_MB` is an optional parameter. It indicates the max volume size for that user.

Now you have a docker instance running `netatalk`.
* `TM_SIZE_MB` is an optional parameter. It indicates the max Time Machine size for that user.


### Step 3 - Enable Auto Discovery
Expand All @@ -62,15 +79,16 @@ Avahi isn't built into this Docker image because, due to Docker's networking lim

* Install `avahi-daemon`: run `sudo apt-get install avahi-daemon avahi-utils`
* Copy the file from `avahi/nsswitch.conf` to `/etc/nsswitch.conf`
* Copy the service description file from `avahi/afpd.service` to `/etc/avahi/services/afpd.service`
* Copy the service description file from `avahi/smbd.service` to `/etc/avahi/services/smbd.service`
* Replace VOL_NAME with same name as by adding user `sudo nano /etc/avahi/services/smbd.service`.
* Restart Avahi's daemon: `sudo /etc/init.d/avahi-daemon restart`


### Step 4 - Configure Your Firewall

Make sure

* your server can receive traffic on port `548` and `636` (e.g., `ufw allow 548`, (`636` respectively)).
* your server can receive traffic on the ports used by the container

* your Mac allows outgoing connections (Little Snitch?)

Expand All @@ -82,7 +100,7 @@ To start using it, follow these steps:

* If you use Avahi, open **Finder**, go to **Shared** and connect to your server with your new username and password.

* Alternatively (or if you don't use Avahi) from **Finder** press **CMD-K** and type `afp://your-server` where `your-server` can be your server's name or IP address (e.g., `afp://my-server` or `afp://192.168.0.5`).
* Alternatively (or if you don't use Avahi) from **Finder** press **CMD-K** and type `smb://your-server` where `your-server` can be your server's name or IP address (e.g., `smb://my-server` or `smb://192.168.0.5`).

* Go to **System Preferences**, and open **Time Machine** settings.

Expand All @@ -103,10 +121,10 @@ You can configure the container using environment variables (for example, if you

There are these environment variables:

* **AFP_LOGIN**: User name
* **AFP_PASSWORD**: User password
* **AFP_NAME**: Name of the volume
* **AFP_SIZE_LIMIT**: Size in MB of the volume (optional)
* **SMB_LOGIN**: User name
* **SMB_PASSWORD**: User password
* **SMB_NAME**: Name of the volume
* **TM_SIZE_LIMIT**: Time Machine size limit in MB (optional)
* **PUID**: For UID
* **PGID**: For GID

Expand All @@ -123,7 +141,7 @@ To find your `PUID` and `GUID` use `id user` as below:

#### I got Docker running, my firewall is configured, but I still don't find the service in Time Machine.

Make sure you actually mount the server volume (see Step 5) before trying to find it in Time Machine settingss.
Make sure you actually mount the server volume (see Step 5) before trying to find it in Time Machine settings.


### My container restarted and I can't login
Expand All @@ -136,31 +154,39 @@ Alternativey, you can script the account creation and upload a custom entrypoint
set -e

# Repeat for all your accounts
add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [VOL_SIZE_MB]
add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [VOL_SIZE_MB]
add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [TM_SIZE_MB]
add-account USERNAME PASSWORD VOL_NAME VOL_ROOT [TM_SIZE_MB]
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
```

Save the above file as `entrypoint.sh` and make sure it is marked as executable (`chmod +x entrypoint.sh`). Then invoke `docker run` as:

```
$ docker run -h timemachine --name timemachine --restart=unless-stopped -d -v /external_volume:/timemachine -it -p 548:548 -p 636:636 -v entrypoint.sh:/entrypoint.sh odarriba/timemachine-rpi
$ docker run -h timemachine \
--name timemachine \
--restart=unless-stopped \
-dit \
-v /external_volume:/timemachine \
-p 137:137/udp \
-p 138:138/udp \
-p 139:139/tcp \
-p 445:445/tcp \
-v entrypoint.sh:/entrypoint.sh \
odarriba/timemachine
```

#### I am still having trouble ...

* The idea of using avahi-daemon installed in the bare metal server is to avoid having to execute the container with --net=host, which a potentially insecure flag. But, as the last option to check things out, it should be fine. You just should know what you are enabling.

* A Time Machine network disk is just a disk image in an AFP volume that supports the correct level of encryption. So to be recognised by the TimeMachine daemon, you should mount the unit manually for the first time, configure TimeMachine on your computer, and then the OS will do that for you automatically.

* A Time Machine network disk is just a disk image in an SMB volume that supports the correct level of encryption. So to be recognised by the Time Machine daemon, you should mount the unit manually for the first time, configure Time Machine on your computer, and then the OS will do that for you automatically.


#### Why do I need to install Avahi on your host and not in the container?

Because if you don't do it this way, the discovery message won't be able to reach your computers.



## Contributors

* Óscar de Arriba ([email protected])
Expand Down
57 changes: 57 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Upgrade guide: from AFP to SMB

## Why you should switch to the SMB version?

Because of **performance** and **stability**. Apple has deprecated AFP and they
only support Samba now as the network protocol for Time Machine.

AFP still works, but it is not maintained and it will probably stop working in
future versions of OSX.

Also, we could see amazing performance improvements in some scenarios (like
using Wi-Fi conections for backup).

## Will I lose my old backups?

**No.**

The disk format is still the same, so only the transfer protocol will change.
Time Machine will recognise the old backup and will continue using it.

## Migration isntructions

1. First of all, check that your backups are inside your host machine using a
volume.

That means, check that you can find your backup folder in your disk and that
there are contents inside. If you followed the instructions of the README, the
data should be there.

2. Stop all Time Machine process in your Macs. To do that, enter on
`Preferences > Time Machine` and check that there is no backup in progress.

3. Stop current timemachine container and remove it:
```
$ docker stop timemachine
$ docker rm timemachine
```

4. Remove local image:
```
$ docker rmi odarriba/timemachine
```

5. Follow current version instructions to start the new container. Check that:
- you use the same data directory as before
- you create the same users as before (with same UID and GID if you specified them)

**Note** The ENV vars have changed, and now all `AFP_` are `SMB_`. if you use
them in a docker compose file, you should update them.

6. in all your macs, connect again to the server:
- Connect to your server as explained in the README, using `smb://` instead of
`afp://`.
- Go to `Preferences > Time Machine` and click on `Select disk`.
- Select your new server
- Time Machine will ask to use the previous backup (if you keeped it) and will
ask for it's password if it was encrypted.
5 changes: 0 additions & 5 deletions afp.conf

This file was deleted.

14 changes: 0 additions & 14 deletions avahi/afpd.service

This file was deleted.

20 changes: 20 additions & 0 deletions avahi/smbd.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
<port>445</port>
</service>
<service>
<type>_device-info._tcp</type>
<port>9</port>
<txt-record>model=TimeCapsule8,119</txt-record>
</service>
<service>
<type>_adisk._tcp</type>
<port>9</port>
<txt-record>dk0=adVN=<REPLACE with VOL_NAME>,adVF=0x82</txt-record>
<txt-record>sys=adVF=0x100</txt-record>
</service>
</service-group>
Loading