├── README.md ├── qubes-rsync-forwarder.socket ├── qubes-rsync-forwarder@.service ├── qubes-ssh-forwarder.socket ├── qubes-ssh-forwarder@.service ├── qubes.Rsync ├── qubes.ssh └── rsyncd.conf /README.md: -------------------------------------------------------------------------------- 1 | # Qubes rsync 2 | 3 | Sometimes there is a need for a central document store to which other qubes have access. 4 | This is a simple tool that allows individual qubes read/write access to the store using rsync, rather than using `qvm-copy` or `qvm-move`. 5 | rsync runs as a daemon on the store, and client qubes access it using rsync over qrexec. 6 | 7 | The rsync daemon is configured,(as normal), by editing a config file at `/etc/rsyncd.conf`. 8 | The default setting is to have a **read/write** store at `/home/user/shared`, and a **read only** directory at `/home/user/archive`. 9 | You must create these directories on the rsync server. 10 | All the usual rsync configuration options are available, and you can create other shared directories as you want. 11 | **N.B. Because access appears to come from localhost, host control directives will not work** 12 | 13 | Of course, access is controlled with the usual qubes-rpc policy file. 14 | **You must consider the security implications in sharing data between qubes.** 15 | 16 | ## How to use it 17 | 18 | I really should package this properly. 19 | 20 | In the meantime: 21 | Install rsync in the template. 22 | Copy `rsyncd.conf` to `/etc` 23 | Copy `qubes.Rsync` to `/etc/qubes-rpc` 24 | `chmod +x /etc/qubes-rpc/qubes.Rsync` 25 | Copy `qubes-rsync-forwarder@.service` to `/lib/systemd/system` 26 | Copy `qubes-rsync-forwarder.socket` to `/lib/systemd/system` 27 | 28 | ### On the server: 29 | Create `/home/user/shared` and `/home/user/archive`, and populate with data. 30 | chmod as appropriate: 31 | `chmod 777 /home/user/shared.` 32 | 33 | Start the rsync service: 34 | `systemctl start rsync` 35 | 36 | 37 | ### On the clients: 38 | Enable the `rsync-setup` service in the client. (This doesn't exist as yet, but should check that rsync is installed and forwarder is enabled). 39 | Start the forwarder: 40 | `systemctl enable qubes-rsync-forwarder.socket` 41 | `systemctl start qubes-rsync-forwarder.socket` 42 | ` 43 | 44 | Then on the clients use rsync as normal: 45 | `rsync --port=837 localhost::shared` 46 | 47 | ### Making it start automatically. 48 | I prefer to start the server manually. 49 | If you want the rsync service to start automatically, put an entry in `/rw/config/rc.local`: 50 | `systemctl start rsync` 51 | 52 | Similarly, if you want the clients set up automatically, add the start commands to `/rw/config/rc.local` in a client qube. 53 | 54 | ### Configuring policy 55 | In Qubes 4.1, add these lines to /etc/qubes/policy.d/30-user.policy. (Create that file if it does not exist.) 56 | `qubes.Rsync * CLIENT @default allow target=SERVER` 57 | Change CLIENT to the name of your client qubes, and SERVER to the name of your rsync server. 58 | *The clients do not know the name of the server qube* 59 | 60 | ### Customising 61 | You can create more shared folders, and make them accessible by customising the /etc/rsyncd.conf file. 62 | If you have more than one rsync server qube, you can use [bind-dirs](https://www.qubes-os.org/doc/bind-dirs/) to change the available folders on each server qube. 63 | 64 | # Qubes sshfs 65 | 66 | The greatest problem with the rsync solution is that it makes *copies* of the files or directories. 67 | This may be fine, but with large files, or large numbers of files, there's a significant overhead. 68 | What would be better would be to allow clients to access files on the "server" qube directly. 69 | 70 | The simplest method is to use sshfs to make the remote files available to clients over qrexec. 71 | Of course, you could do this using NFS, or any other network based file sharing protocol. 72 | 73 | Again, this is not packaged. 74 | 75 | As root: 76 | Install a ssh-server and sshfs in the template. (` apt install openssh-server sshfs`). 77 | (Follow the usual advice when installing services in Debian templates.) 78 | `cp qubes.ssh /etc/qubes-rpc` 79 | `cp qubes-ssh-forwarder@.service lib/systemd/system` 80 | `cp qubes-ssh-forwarder.socket /lib/systemd/system` 81 | 82 | ## Create ssh-keys for passwordless login. 83 | 84 | In the client run `ssh-keygen` with defaults: you can choose whether to set a password or not. 85 | `qvm-copy .ssh/id_rsa.pub` to the server. 86 | 87 | On the server, `mkdir .ssh && cat QubesIncoming//id_rsa.pub >> .ssh/authorized_keys` 88 | 89 | ### On the server: 90 | There's a little set-up to do, as root: 91 | `mkdir /home/tx` 92 | `chmod 777 /home/tx` 93 | `systemctl start sshd` 94 | 95 | ### On the clients: 96 | Enable the `ssh-setup` service in the client. (This doesn't exist as yet, but should check that ssh is installed and forwarder is enabled). 97 | `systemctl enable qubes-ssh-forwarder.socket` 98 | `systemctl start qubes-ssh-forwarder.socket` 99 | 100 | As *user*: 101 | `mkdir /home/user/tx` 102 | `sshfs -p 840 localhost:/home/tx tx` 103 | 104 | Now `/home/tx` on the server is mounted at `/home/user/tx` on the client. 105 | 106 | Access can be controlled using the usual qubes-rpc mechanism, by editing a policy file. 107 | 108 | It would be possible to constrain access to files on the server, using (e.g) ssh chroots, and access control mechanisms. 109 | -------------------------------------------------------------------------------- /qubes-rsync-forwarder.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Forward connection to rsync over Qubes RPC 3 | ConditionPathExists=/var/run/qubes-service/rsync-setup 4 | 5 | [Socket] 6 | ListenStream=127.0.0.1:837 7 | BindToDevice=lo 8 | Accept=true 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /qubes-rsync-forwarder@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Forward connection to rsync over Qubes RPC 3 | 4 | [Service] 5 | ExecStart=/usr/bin/qrexec-client-vm '' qubes.Rsync 6 | StandardInput=socket 7 | StandardOutput=inherit 8 | -------------------------------------------------------------------------------- /qubes-ssh-forwarder.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Forward connection to ssh over Qubes RPC 3 | ConditionPathExists=/var/run/qubes-service/ssh-setup 4 | 5 | [Socket] 6 | ListenStream=127.0.0.1:840 7 | BindToDevice=lo 8 | Accept=true 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /qubes-ssh-forwarder@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Forward connection to ssh over Qubes RPC 3 | 4 | [Service] 5 | ExecStart=/usr/bin/qrexec-client-vm '' qubes.ssh 6 | StandardInput=socket 7 | StandardOutput=inherit 8 | -------------------------------------------------------------------------------- /qubes.Rsync: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec socat STDIO TCP:localhost:873 3 | -------------------------------------------------------------------------------- /qubes.ssh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec socat STDIO TCP:localhost:22 3 | -------------------------------------------------------------------------------- /rsyncd.conf: -------------------------------------------------------------------------------- 1 | # rsyncd.conf configuration file 2 | 3 | # GLOBAL OPTIONS 4 | 5 | #motd file=/etc/motd 6 | #log file=/var/log/rsyncd 7 | # for pid file, do not use /var/run/rsync.pid if 8 | # you are going to run rsync out of the init.d script. 9 | # The init.d script does its own pid file handling, 10 | # so omit the "pid file" line completely in that case. 11 | # pid file=/var/run/rsyncd.pid 12 | #syslog facility=daemon 13 | #socket options= 14 | port = 873 15 | 16 | # MODULE OPTIONS 17 | 18 | [shared] 19 | path = /home/user/shared 20 | comment = Shared r/w area 21 | read only = no 22 | 23 | [archive] 24 | path = /home/user/archive 25 | comment = Shared read only area 26 | read only = yes 27 | 28 | --------------------------------------------------------------------------------