| | 1 | {{{ |
| | 2 | =============================== |
| | 3 | Tutorial for Tahoe-LAFS (Draft) |
| | 4 | =============================== |
| | 5 | }}} |
| | 6 | = Hosts setup = |
| | 7 | |
| | 8 | In this tutorial we're gonna setup 3 nodes, whatever they are (Host+VM1+VM2) |
| | 9 | |
| | 10 | IPs and hosts are: |
| | 11 | * 172.16.23.1 (host.local : Mac OS X 10.6.4) |
| | 12 | * 172.16.23.128 (vm1.local : Debian GNU/Linux 5.0) |
| | 13 | * 172.16.23.130 (vm2.local : Debian GNU/Linux 5.0) |
| | 14 | |
| | 15 | I'll use a self-explanatory prompt for each host. |
| | 16 | |
| | 17 | = Installation on each node = |
| | 18 | |
| | 19 | I like pypi so much I find it easier to do the download, extraction, |
| | 20 | get dependencies and build using it. |
| | 21 | {{{ |
| | 22 | # easy_install -U allmydata-tahoe |
| | 23 | }}} |
| | 24 | it failed on the freshly installed debian, with that error : |
| | 25 | {{{ |
| | 26 | ImportError: No module named darcsver.setuptools_command |
| | 27 | }}} |
| | 28 | A fast look on google, showed that installing setuptools_darcs and |
| | 29 | darcsver don't build as expected and may be missing at install time. |
| | 30 | The fix is to install them first, and only then install tahoe. |
| | 31 | {{{ |
| | 32 | # easy_install -U setuptools_darcs darcsver |
| | 33 | # easy_install -U allmydata-tahoe |
| | 34 | }}} |
| | 35 | then execute tahoe --vesion to check everything is installed as |
| | 36 | expected : |
| | 37 | |
| | 38 | on debian : |
| | 39 | {{{ |
| | 40 | % tahoe --version |
| | 41 | allmydata-tahoe: 1.7.1, foolscap: 0.5.1, pycryptopp: 0.5.17-r683, zfec: 1.4.7, Twisted: 10.0.0, Nevow: 0.10.0, zope.interface: 3.5.1, python: 2.6.1, platform: Darwin-10.4.0-i386-64bit, sqlite: 3.6.12, simplejson: 2.1.1, argparse: 1.1, pycrypto: 2.1.0, pyOpenSSL: 0.7, pyutil: 1.7.7, zbase32: 1.1.1, setuptools: 0.6c15dev, pyasn1: 0.0.11a, pysqlite: 2.4.1 |
| | 42 | }}} |
| | 43 | on MacOSX : |
| | 44 | {{{ |
| | 45 | % tahoe --version |
| | 46 | allmydata-tahoe: 1.7.1, foolscap: 0.5.1, pycryptopp: 0.5.19, zfec: 1.4.7, Twisted: 10.0.0, Nevow: 0.10.0, zope.interface: 3.6.1, python: 2.5.2, platform: Linux-debian_5.0-x86_64-64bit, sqlite: 3.5.9, simplejson: 2.1.1, argparse: 1.1, pycrypto: 2.1.0, pyOpenSSL: 0.7, pyutil: 1.7.7, zbase32: 1.1.1, setuptools: 0.6c12dev, pyasn1: 0.0.11a, pysqlite: 2.3.2 |
| | 47 | }}} |
| | 48 | now Tahoe is installed \o/ |
| | 49 | |
| | 50 | = Instanciate the nodes = |
| | 51 | |
| | 52 | So, after reading running.html, configuration.txt and architecture.txt, we'll first |
| | 53 | create an introducer node, that will get every other nodes to know each other. The |
| | 54 | documentation says that we have to create and launch the introducer as follows (that |
| | 55 | we do on vm1.local) |
| | 56 | {{{ |
| | 57 | vm1% mkdir tahoe-introducer |
| | 58 | vm1% tahoe create-introducer tahoe-introducer |
| | 59 | Introducer created in tahoe-introducer |
| | 60 | vm1% tahoe start tahoe-introducer |
| | 61 | STARTING /home/guyzmo/tahoe-introducer |
| | 62 | introducer node probably started |
| | 63 | vm1% cat tahoe-introducer/introducer.furl |
| | 64 | pb://6oibvp5whrb3v3ge7ajuyapooswsda2e@172.16.23.128:33272,127.0.0.1:33272/introducer |
| | 65 | }}} |
| | 66 | Then we copy that last string we got from 'cat', and paste it in tahoe.cfg, |
| | 67 | as follows (edit it using your favorite editor, mine is vim) : |
| | 68 | {{{ |
| | 69 | vm2% vim ~/.tahoe/tahoe.cfg |
| | 70 | -------------8<----------------------8<---------------- |
| | 71 | 22 [client] |
| | 72 | 23 introducer.furl = pb://6oibvp5whrb3v3ge7ajuyapooswsda2e@172.16.23.128:33272,127.0.0.1:33272/introducer |
| | 73 | 24 helper.furl = |
| | 74 | 25 #key_generator.furl = |
| | 75 | 26 #stats_gatherer.furl = |
| | 76 | 27 #shares.needed = 3 |
| | 77 | 28 #shares.happy = 7 |
| | 78 | 29 #shares.total = 10 |
| | 79 | ------------->8---------------------->8---------------- |
| | 80 | }}} |
| | 81 | exit, and then do the same on 'host'. |
| | 82 | |
| | 83 | finally, execute on 'vm2' and 'host' the following : |
| | 84 | {{{ |
| | 85 | vm2% tahoe start |
| | 86 | STARTING /home/guyzmo/.tahoe |
| | 87 | client node probably started |
| | 88 | |
| | 89 | host% tahoe start |
| | 90 | STARTING /home/guyzmo/.tahoe |
| | 91 | client node probably started |
| | 92 | }}} |
| | 93 | wait a bit and do : |
| | 94 | {{{ |
| | 95 | % ps aux | grep tahoe |
| | 96 | myuser 5360 1.2 7.4 158820 28348 ? S< 02:13 0:00 /usr/bin/python /usr/bin/twistd -y tahoe-client.tac --logfile logs/twistd.log |
| | 97 | }}} |
| | 98 | and you shall see an output that looks alike. If not, tahoe failed to start. |
| | 99 | You've got to check ~/.tahoe/logs/ what got wrong. |
| | 100 | |
| | 101 | = Configure the nodes = |
| | 102 | |
| | 103 | Now, let's do some configuration. On each node edit tahoe.cfg : |
| | 104 | {{{ |
| | 105 | host% vim ~/.tahoe/tahoe.cfg |
| | 106 | -------------8<----------------------8<---------------- |
| | 107 | 10 [node] |
| | 108 | 11 nickname = client-host |
| | 109 | 12 web.port = tcp:3456:interface=172.16.23.1 |
| | 110 | ------------->8---------------------->8---------------- |
| | 111 | host% tahoe restart |
| | 112 | }}} |
| | 113 | |
| | 114 | {{{ |
| | 115 | vm1% vim ~/tahoe-introducer/tahoe.cfg |
| | 116 | -------------8<----------------------8<---------------- |
| | 117 | 10 [node] |
| | 118 | 11 nickname = introducer-vm1 |
| | 119 | 12 web.port = tcp:3456:interface=172.16.23.128 |
| | 120 | ------------->8---------------------->8---------------- |
| | 121 | vm1% tahoe restart ~/tahoe-introducer |
| | 122 | |
| | 123 | vm2% vim ~/.tahoe/tahoe.cfg |
| | 124 | -------------8<----------------------8<---------------- |
| | 125 | 10 [node] |
| | 126 | 11 nickname = client-vm2 |
| | 127 | 12 web.port = tcp:3456:interface=172.16.23.130 |
| | 128 | ------------->8---------------------->8---------------- |
| | 129 | vm2% tahoe restart |
| | 130 | }}} |
| | 131 | |
| | 132 | Then get your favorite browser and browse to the following URLs, you |
| | 133 | should get pages similar to the ones below |
| | 134 | |
| | 135 | * http://172.16.23.1:3456/ -> http://m0g.net/~guyzmo/172.16.23.1_3456_1.png |
| | 136 | * http://172.16.23.128:3456/ -> http://m0g.net/~guyzmo/172.16.23.128_3456_1.png |
| | 137 | * http://172.16.23.130:3456/ -> http://m0g.net/~guyzmo/172.16.23.130_3456_1.png |
| | 138 | |
| | 139 | Now it's time to be able to store something on the grid, as |
| | 140 | the whole purpose of Tahoe-LAFS, and thus of this tutorial is |
| | 141 | to get a grid to store files. |
| | 142 | |
| | 143 | On host and vm2, edit again ~/.tahoe/tahoe.cfg and modify it |
| | 144 | as follows : |
| | 145 | |
| | 146 | {{{ |
| | 147 | vm2% vim ~/.tahoe/tahoe.cfg |
| | 148 | -------------8<----------------------8<---------------- |
| | 149 | 31 [storage] |
| | 150 | 32 enabled = true |
| | 151 | 33 readonly = false |
| | 152 | 34 reserved_space = 1GB # here you tell the storage server how much space you would like to use |
| | 153 | ------------->8---------------------->8---------------- |
| | 154 | vm2% tahoe restart |
| | 155 | }}} |
| | 156 | |
| | 157 | and the same on host. |
| | 158 | |
| | 159 | The result would be as follows : |
| | 160 | |
| | 161 | * http://172.16.23.1:3456/ -> http://m0g.net/~guyzmo/172.16.23.1_3456_2.png |
| | 162 | * http://172.16.23.128:3456/ -> http://m0g.net/~guyzmo/172.16.23.128_3456_2.png |
| | 163 | * http://172.16.23.130:3456/ -> http://m0g.net/~guyzmo/172.16.23.130_3456_2.png |
| | 164 | |
| | 165 | Then, you've got a working Tahoe-LAFS grid working ! |
| | 166 | Is that all ? Well, no, it's time to learn how to use it. |
| | 167 | |
| | 168 | = File capabilities ? = |
| | 169 | |
| | 170 | Now it's time for a bit of litterature. |
| | 171 | |
| | 172 | TODO |
| | 173 | |
| | 174 | = Access your shares = |
| | 175 | |
| | 176 | You can store and access files on Tahoe-LAFS using a lot of |
| | 177 | different ways. The fatest is to either use the Web UI, or |
| | 178 | the CLI though you need to remember the caps of the files. |
| | 179 | |
| | 180 | Using the WUI is straight forward, connect to a storage client, |
| | 181 | use the forms to add/get/remove files and directories. Just |
| | 182 | always remember that once you created a directory, you need to |
| | 183 | save the file's URI, or you won't be able to find it again later |
| | 184 | on. |
| | 185 | |
| | 186 | == Using the CLI == |
| | 187 | |
| | 188 | The CLI behaves mostly like a standard shell, with all |
| | 189 | commands prefixed by 'tahoe', the same way version control |
| | 190 | system work. |
| | 191 | |
| | 192 | If you execute for the first time : |
| | 193 | |
| | 194 | {{{ |
| | 195 | % tahoe ls |
| | 196 | error: No alias specified, and the default 'tahoe' alias doesn't exist. To create it, use 'tahoe create-alias tahoe'. |
| | 197 | }}} |
| | 198 | |
| | 199 | you'll get that error. That's why you need to create a |
| | 200 | 'root' directory for CLI commands that will be aliased |
| | 201 | to the 'tahoe:' prefix. |
| | 202 | |
| | 203 | {{{ |
| | 204 | % tahoe create-alias tahoe |
| | 205 | [...] |
| | 206 | socket.error: [Errno 61] Connection refused |
| | 207 | }}} |
| | 208 | |
| | 209 | What happens here is that the Tahoe client tries to connect to the URL |
| | 210 | given in the ~/.tahoe/node.url file. So, you need to edit ~/.tahoe/node.url |
| | 211 | {{{ |
| | 212 | host% vim ~/.tahoe/node.url |
| | 213 | -------------8<----------------------8<---------------- |
| | 214 | 1 http://172.16.23.1:3456/ |
| | 215 | ------------->8---------------------->8---------------- |
| | 216 | }}} |
| | 217 | {{{ |
| | 218 | vm2% vim ~/.tahoe/node.url |
| | 219 | -------------8<----------------------8<---------------- |
| | 220 | 1 http://172.16.23.1:3456/ |
| | 221 | ------------->8---------------------->8---------------- |
| | 222 | }}} |
| | 223 | |
| | 224 | HINT: each time you do 'tahoe start' node.url gets reset to 127.0.0.1. If you |
| | 225 | want to intensively use the CLI, change |
| | 226 | 'web.port = tcp:3456:interface=172.16.23.1' |
| | 227 | to |
| | 228 | 'web.port = tcp:3456' |
| | 229 | in tahoe.cfg. Specifying the interface to listen on is usually a good security |
| | 230 | policy, though twisted supports only one interface declaration, or all interfaces |
| | 231 | if you don't declare it. |
| | 232 | |
| | 233 | Now, you can run the previous command : |
| | 234 | |
| | 235 | {{{ |
| | 236 | % tahoe create-alias tahoe |
| | 237 | Alias 'tahoe' created |
| | 238 | }}} |
| | 239 | |
| | 240 | What it has actually done, is that it edited the ~/.tahoe/private/aliases file |
| | 241 | linking the keyword you gave with a file cap : |
| | 242 | |
| | 243 | {{{ |
| | 244 | vm2% cat ~/.tahoe/private/aliases |
| | 245 | tahoe: URI:DIR2:bfe7inwcduobfnnrxocqechr4q:huurbpkrtajzdrq6okvxxppj5negccz4payh6gxes5nphe6djbeq |
| | 246 | }}} |
| | 247 | and |
| | 248 | {{{ |
| | 249 | host% cat ~/.tahoe/private/aliases |
| | 250 | tahoe: URI:DIR2:ozgebrm5oe52hhcnxhbc6oy6xu:7cyu73izd6q6w4kwngyxxdu7ttuzwy5kl2uybcrqohhen362crla |
| | 251 | }}} |
| | 252 | so, as you can see, different tahoe CLI won't work in the same base directories. |
| | 253 | If you really want to enable this, copy the same aliases file on every account |
| | 254 | you want to use the CLI on. |
| | 255 | |
| | 256 | Finally, to use the CLI, have a look at 'tahoe help' for a full description |
| | 257 | of the commands. |
| | 258 | |
| | 259 | For example, here are some basic commands: |
| | 260 | |
| | 261 | {{{ |
| | 262 | % tahoe cp README.txt tahoe: |
| | 263 | Success: file copied |
| | 264 | % tahoe ls -l tahoe: |
| | 265 | -r-- 1348 Aug 04 12:52 README.txt |
| | 266 | % tahoe get tahoe:README.txt | head |
| | 267 | =============================== |
| | 268 | Tahoe-LAFS |
| | 269 | =============================== |
| | 270 | |
| | 271 | Tahoe-LAFS is a Free Software/Open Source decentralized data store. It |
| | 272 | distributes your filesystem across multiple servers, and even if some of the |
| | 273 | servers fail or are taken over by an attacker, the entire filesystem continues |
| | 274 | to work correctly and to preserve your privacy and security. |
| | 275 | |
| | 276 | To get started please see `quickstart.html`_. |
| | 277 | }}} |
| | 278 | |
| | 279 | == Using the FTP interface == |
| | 280 | |
| | 281 | As Tahoe does not have user accounts management, to enable FTP access, |
| | 282 | we need first to enable authentication and associate root caps to each |
| | 283 | user allowed to access the system. |
| | 284 | |
| | 285 | /!\ Be sure to have installed twisted version >=10.1 before trying FTP/sFTP |
| | 286 | interface, tahoe's ftp feature is not compatible with prior versions. |
| | 287 | |
| | 288 | For more informations about FTP/sFTP configuration refer to the documentation: |
| | 289 | * http://tahoe-lafs.org/source/tahoe-lafs/trunk/docs/frontends/FTP-and-SFTP.txt |
| | 290 | * http://tahoe-lafs.org/trac/tahoe-lafs/wiki/SftpFrontend |
| | 291 | |
| | 292 | === Account file creation === |
| | 293 | |
| | 294 | The password file is using a very simple format, each non blank/commented |
| | 295 | line is following this template : |
| | 296 | {{{ |
| | 297 | USER PASSWORD ROOTCAP |
| | 298 | }}} |
| | 299 | so we're gonna setup two users the following way on host: |
| | 300 | {{{ |
| | 301 | host% tahoe create-alias alice |
| | 302 | Alias 'alice' created |
| | 303 | host% tahoe create-alias bob |
| | 304 | Alias 'bob' created |
| | 305 | host% cat ~/.tahoe/private/aliases |
| | 306 | tahoe: URI:DIR2:ozgebrm5oe52hhcnxhbc6oy6xu:7cyu73izd6q6w4kwngyxxdu7ttuzwy5kl2uybcrqohhen362crla |
| | 307 | alice: URI:DIR2:dhl2wcuoppuirtv3gk2lslhx6i:nur5sar5lwfxal63gcjaysu4mxt33l35uw4bqtokby3airqhwehq |
| | 308 | bob: URI:DIR2:r2dwmysrl4wigiov52fmifs2mi:2fdu2l3jxuqupepefmkd3y5vftqatc62vl6elmb5qlgi3gmvpx6a |
| | 309 | host% cat > ~/.tahoe/private/ftp.accounts |
| | 310 | alice h3rp4ssw0rd URI:DIR2:dhl2wcuoppuirtv3gk2lslhx6i:nur5sar5lwfxal63gcjaysu4mxt33l35uw4bqtokby3airqhwehq |
| | 311 | bob h1sp4ssw0rd URI:DIR2:r2dwmysrl4wigiov52fmifs2mi:2fdu2l3jxuqupepefmkd3y5vftqatc62vl6elmb5qlgi3gmvpx6a |
| | 312 | host% |
| | 313 | }}} |
| | 314 | and two users on vm2: |
| | 315 | {{{ |
| | 316 | vm2% tahoe create-alias alice |
| | 317 | Alias 'alice' created |
| | 318 | vm2% tahoe add-alias bob URI:DIR2:r2dwmysrl4wigiov52fmifs2mi:2fdu2l3jxuqupepefmkd3y5vftqatc62vl6elmb5qlgi3gmvpx6a |
| | 319 | vm2% cat ~/.tahoe/private/aliases |
| | 320 | tahoe: URI:DIR2:ozgebrm5oe52hhcnxhbc6oy6xu:7cyu73izd6q6w4kwngyxxdu7ttuzwy5kl2uybcrqohhen362crla |
| | 321 | alice: URI:DIR2:x3y3i3s6h5l7gspse6ol4b7goy:zinwdjlffv23gbv5umyjqcdg3trfmvxdwc77cwae3cpxw6mhtq5a |
| | 322 | bob: URI:DIR2:r2dwmysrl4wigiov52fmifs2mi:2fdu2l3jxuqupepefmkd3y5vftqatc62vl6elmb5qlgi3gmvpx6a |
| | 323 | vm2% cat > ~/.tahoe/private/ftp.accounts |
| | 324 | alice h3rp4ssw0rd URI:DIR2:x3y3i3s6h5l7gspse6ol4b7goy:zinwdjlffv23gbv5umyjqcdg3trfmvxdwc77cwae3cpxw6mhtq5a |
| | 325 | bob h1sp4ssw0rd URI:DIR2:r2dwmysrl4wigiov52fmifs2mi:2fdu2l3jxuqupepefmkd3y5vftqatc62vl6elmb5qlgi3gmvpx6a |
| | 326 | vm2% |
| | 327 | }}} |
| | 328 | |
| | 329 | If you look carefully to both logs, alice gets two root caps on each target host, |
| | 330 | while bob is getting the same root cap on both. Of course, the alias creation is |
| | 331 | optional, but handy for the grid manager to control what the users have. |
| | 332 | |
| | 333 | now, let's update the configuration : |
| | 334 | {{{ |
| | 335 | % vim ~/.tahoe/tahoe.cfg |
| | 336 | -------------8<----------------------8<---------------- |
| | 337 | 22 [ftpd] |
| | 338 | 23 enabled = true |
| | 339 | 24 port = 8021 |
| | 340 | 25 accounts.file = private/ftp.accounts |
| | 341 | ------------->8---------------------->8---------------- |
| | 342 | % tahoe restart |
| | 343 | STOPPING /home/guyzmo/.tahoe |
| | 344 | process 3063 is dead |
| | 345 | STARTING /home/guyzmo/.tahoe |
| | 346 | client node probably started |
| | 347 | }}} |
| | 348 | |
| | 349 | and then, connect your FTP client to tahoe's FTP server: |
| | 350 | |
| | 351 | {{{ |
| | 352 | % tahoe cp foobar.jpg bob: |
| | 353 | Success: files copied |
| | 354 | % lftp bob:h1sp4ssw0rd@172.16.23.1:8021 |
| | 355 | lftp bob@172.16.23.1:/> ls |
| | 356 | -rw------- 1 bob bob 857648 Jan 01 1970 foobar.jpg |
| | 357 | lftp bob@172.16.23.1:/> exit |
| | 358 | % lftp alice:h3rp4ssw0rd@172.16.23.1:8021 |
| | 359 | lftp alice@172.16.23.1:~> put cliclac.jpg |
| | 360 | 857648 bytes transferred |
| | 361 | lftp alice@172.16.23.1:~> ls |
| | 362 | -rw------- 1 alice alice 857648 Jan 01 1970 foobar.jpg |
| | 363 | lftp alice@172.16.23.1:/> exit |
| | 364 | % lftp bob:h1sp4ssw0rd@172.16.23.130:8021 |
| | 365 | lftp bob@172.16.23.130:~> ls |
| | 366 | -rw------- 1 bob bob 857648 Jan 01 1970 foobar.jpg |
| | 367 | lftp bob@172.16.23.130:/> exit |
| | 368 | % lftp alice:h3rp4ssw0rd@172.16.23.130:8021 |
| | 369 | lftp alice@172.16.23.130:~> ls |
| | 370 | lftp alice@172.16.23.130:/> exit |
| | 371 | }}} |
| | 372 | |
| | 373 | et voilà ! |
| | 374 | |
| | 375 | == Configure sFTP access == |
| | 376 | |
| | 377 | The procedure is slightly the same as for ftp access. You need to have the |
| | 378 | ftp.accounts files placed in ~/.tahoe/private/, and we'll consider you already |
| | 379 | have the one written in the previous section. |
| | 380 | |
| | 381 | /!\ As for FTP access, you need to have twisted version >=10.1.0 installed |
| | 382 | before trying to use tahoe's sFTP feature. |
| | 383 | |
| | 384 | {{{ |
| | 385 | % ssh-keygen -f ~/.tahoe/private/ssh_host_rsa_key |
| | 386 | Generating public/private rsa key pair. |
| | 387 | Enter passphrase (empty for no passphrase): |
| | 388 | Enter same passphrase again: |
| | 389 | Your identification has been saved in /home/guyzmo/.tahoe/private/ssh_host_rsa_key. |
| | 390 | Your public key has been saved in /home/guyzmo/.tahoe/private/ssh_host_rsa_key.pub. |
| | 391 | The key fingerprint is: |
| | 392 | 3f:a6:c7:38:19:3a:19:3c:ee:77:d5:5a:3d:2f:86:6c guyzmo@vm2 |
| | 393 | The key's randomart image is: |
| | 394 | +--[ RSA 2048]----+ |
| | 395 | | | |
| | 396 | | | |
| | 397 | | | |
| | 398 | | | |
| | 399 | | . S . . | |
| | 400 | | + .. . o..| |
| | 401 | | . = =+o + o| |
| | 402 | | = =o+.E o .| |
| | 403 | | ..o.+ . . . | |
| | 404 | +-----------------+ |
| | 405 | % vim ~/.tahoe/tahoe.cfg |
| | 406 | -------------8<----------------------8<---------------- |
| | 407 | 27 [sftpd] |
| | 408 | 28 enabled = true |
| | 409 | 29 port = 8022 |
| | 410 | 30 host_pubkey_file = private/ssh_host_rsa_key.pub |
| | 411 | 31 host_privkey_file = private/ssh_host_rsa_key |
| | 412 | 32 accounts.file = private/ftp.accounts |
| | 413 | ------------->8---------------------->8---------------- |
| | 414 | % tahoe restart |
| | 415 | STOPPING /home/guyzmo/.tahoe |
| | 416 | process 3101 is dead |
| | 417 | STARTING /home/guyzmo/.tahoe |
| | 418 | client node probably started |
| | 419 | % mkdir ./mnt |
| | 420 | % mount_sshfs -p 8022 bob@172.16.23.1:/ ./mnt/ |
| | 421 | % ls ./mnt/ |
| | 422 | total 1676 |
| | 423 | -rw-rw-rw- luser staff 857648 Aug 4 17:37 foobar.jpg |
| | 424 | }}} |
| | 425 | |
| | 426 | Now, you have a 3 nodes grid running with 1 introducer, 2 storage servers |
| | 427 | and 4 ways to access your files : a WUI, a CLI and accounts for FTP/sFTP |
| | 428 | access. |