Ubuntu Hardy setup - page 1

Your Ubuntu Hardy Slice will be a bare-bones install when it's created. We need to connect via SSH and secure it as soon as possible.


Your new slice

These two articles will take you from a 'barebones' Ubuntu 8.04 (Hardy Heron) Slice to a secured and up-to-date Slice ready for your server software (or whatever you use the Slice for). Not only that, you will have a better understanding of what is going on and, more importantly, why it's going on.

This first part will walk you through setting up a new user and securing login access to your slice.

For convenience when we refer to running a command on your local workstation we will give the command as it would be entered into a Mac or Linux terminal window. For Windows you should be able to adapt the command based on the context. For instance, if you're told to edit a file as part of a step, you would use a text editor like NotePad instead of running the "nano" command.

Intro to SSH

SSH stands for "secure shell". It's a protocol that encrypts data that gets sent back and forth through its connection, making it much harder for someone to intercept that traffic and scan it for passwords or sensitive information. In these articles we'll have you using SSH to connect to your slice to run most administrative commands.

If you're running a Linux desktop, you'll be able to run the ssh commands we list here by using them in a terminal window.

If you're running Mac OS X you'll also be able to run the ssh commands in a terminal window. You can open a terminal by running the 'Terminal' application that was installed with your system.

On Windows you won't have command-line access to SSH by default, so you'll need to download a client. We recommend a program named PuTTY, both because it works well and because it's free. You might also want a nice interface for running scp (which uses the SSH protocol to transmit files over an encrypted connection). We recommend another free program, WinSCP, though there are other options like FileZilla that also work well.

First login

As soon as you have your IP address and password for your Slice, login via SSH:

ssh root@123.45.67.890

As mentioned earlier, on a Windows machine you'll need to run an SSH client like PuTTY in order to make the connection.

If you rebuilt your Slice, you may get a message informing you that the 'remote host identification has changed'.

When you log into a Slice via SSH, one of the security features is matching the remote host with known keys. When you rebuild a Slice, the remote host key changes. As such, your computer thinks there is something dodgy going on.

All you need to do is remove the older entry for the Slice IP. On your LOCAL computer, edit the SSH known_hosts file and remove any entries that point to your Slice IP address.

nano ~/.ssh/known_hosts

If you are not using Linux or a Mac on your LOCAL computer, the location of the known_hosts file will differ depending on the program you are using. You'll need to refer to the documentation for that program for details. For example, PuTTY stores its known hosts in the following registry entry:

HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys

User administration

Now we're logged in to the VPS, immediately change your root password:

passwd

Apart from this initial setup, you should never log in as the root user. It's safer and more secure to create a new administrative user and use the 'sudo' command from that user. Having to use sudo to run superuser commands can help prevent some potentially system-breaking accidents, and it also means that any root-level commands run through sudo will be logged to '/var/log/messages' if later review is needed.

To make managing administrative access to your slice easier let's create a group, 'wheel', that will contain users with sudo privileges. To make the group, run:

/usr/sbin/groupadd wheel

The visudo command used to edit sudo's configuration runs a default editor, and will check the configuration for any syntax errors before saving it. The default editor for Ubuntu Hardy is 'vi', which is an excellent editor but takes some effort to learn. Let's skip that effort for now and temporarily set the default editor to an editor that isn't as powerful, but is easier to use, 'nano':

export EDITOR=/usr/bin/nano

With the group and editor ready, let's issue the 'visudo' command:

/usr/sbin/visudo

Scroll down to the bottom of the file. Add the following two lines to the end of the file:

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

Save and exit the file, and sudo is all set. Members of the 'wheel' group will now have full sudo privileges.

NOTE: Some users will find that while working in the nano editor, the backspace/delete key works backwards, deleting characters in front of the cursor rather than behind it. This can be resolved by editing the '/etc/nanorc' file (with nano, for example) and either uncommenting or adding the line:

set rebinddelete

The corrected behavior will take effect after the file has been saved and nano has been opened again.

Add a new user

Time to create a new administrative user (I've used the name demo here but any name will do).

/usr/sbin/adduser demo

You will be asked to set a password for the new user. The values for Full Name and the rest can be left blank.

Since you'll want to use this user instead of 'root' to manage your system, it will need to be able to use the sudo command. We've already granted that permission to the 'wheel' group, so we just need to add the new user to 'wheel':

/usr/sbin/usermod -a -G wheel demo

SSH keygen

One feature of SSH is the ability to require users to use, instead of a password, a "key pair" for authentication. Under this approach a user generates a public and private key pair on their workstation and then uploads the public half of the key pair to the server. When they go to connect later the server tries to match up its public key with the user's private key in order to authenticate the connection.

Using a key pair with SSH is good security policy, which is why we'll walk you through the process here. A password can be guessed through sheer brute force (running a program to try different character combinations until it gets a match), but a key pair is vastly more complex. It is almost impossible to crack a key pair with a brute force approach.

Note that using a public/private key pair is impractical if you need to log in to your slice from a workstation that is shared with other users. While you can copy the private key to another workstation, putting that key on a shared workstation would defeat the purpose of the key pair's security. In that environment continuing to use a password for SSH access would make sense.

The first step to using key pair authentication is to create a folder to hold your keys. On your LOCAL workstation:

mkdir ~/.ssh

That's assuming you use Linux or a Mac and the folder does not exist. For Windows users we have a separate article on key generation using Puttygen.

To create the ssh keys, on your LOCAL workstation enter:

ssh-keygen -t rsa

If you do not want your key to require a passphrase when used then just press enter when prompted.

That created two files in the .ssh directory: id_rsa and id_rsa.pub. The pub file holds the public key. This is the file that is placed on the Slice.

The other file is your private key. Never share this file with someone else or store it on a public computer.

SSH copy

Now we need to get the public key file onto the Slice.

We'll use the 'scp' command for this as it is an easy and secure means of transferring files.

Still on your LOCAL workstation enter this command, substituting your new username and the IP address of your slice:

scp ~/.ssh/id_rsa.pub demo@123.45.67.890:

When prompted, enter the your user password. When that's done you should see scp copy the file to your user's home directory.

On a Windows machine you'll want to use a third-party client like WinSCP, using the information above to make the connection.

SSH Permissions

OK, so now we've created the public/private keys and we've copied the public key onto the Slice.

Now we need to sort out a few permissions for the ssh key.

On your Slice, create a directory called .ssh in your home directory and move the pub key into it:

mkdir ~demo/.ssh
mv ~demo/id_rsa.pub ~demo/.ssh/authorized_keys

If you haven't run into it before, that squiggly character is the 'tilde', and it's usually in the upper-left of your keyboard. In the Linux shell it can be used as a reference to a user's home directory. Using '~' by itself refers to the current user's home directory, while using it like we did above, '~demo', refers to the home directory of user 'demo'. It's a handy shortcut to know.

Now we can set the correct permissions on the key:

chown -R demo:demo ~demo/.ssh
chmod 700 ~demo/.ssh
chmod 600 ~demo/.ssh/authorized_keys

Again, replace the 'demo' user and group above with the name of the user you created.

Additional users

If you need to add more users to your system, now or after you finish this initial setup, you can just run through the steps above again for each user.

If the user doesn't need to have administrative privileges, skip the part where you add the user to the 'wheel' group.

If the user will be accessed from the same workstation as your administrative user, you can re-use the same public SSH key for the new user.

SSH config

Next we'll change the default SSH configuration to make it more secure:

nano /etc/ssh/sshd_config

You can use this ssh configuration as an example.

The main things to change (or check) are:

Port 30000                           <--- change to a port of your choosing
Protocol 2
PermitRootLogin no
PasswordAuthentication no
UseDNS no
AllowUsers demo

NOTE: The port number can readily be any integer between 1025 and 65536 (inclusive), but should be noted for reference later when any additional listening processes are setup, as it will be important to avoid conflicts.

If you need to allow remote logins for more than one user, add the additional users to the 'AllowUsers' setting separated by spaces.

The labels are fairly self explanatory, but the main security changes to make are to move ssh from the default port of 22 to one of your choosing (we use 30000 in the example), turn off remote root logins, and define which users can log in remotely.

PasswordAuthentication has been turned off because we setup the public/private key earlier. Do note that if you intend to access your slice from different computers you may want leave PasswordAuthentication set to 'yes'. Only use the private key on a secure workstation.

Note that we haven't enabled the new settings — we will restart SSH in a moment, but first we need to create a simple firewall using iptables.

iptables

Right, now we have the basics of logging in and securing SSH done.

Next thing is to set up our iptables (firewall) so we have a more secure installation. It's possible to skip this step, or to disable iptables entirely, but we recommend that if you follow the Slicehost tutorials, you set up iptables with our default rules. It's a good hindrance to would-be intruders. Furthermore, the comments in the file you'll create can help you remember why you made a particular change later, and you can use the examples there to take some of the headache out of figuring out what new rule to add and where.

The default rules

Let's have a look at the default iptables rules:

/sbin/iptables -L

Remember that if you come back to this part of the tutorial as a non-root user later, you'll need to put a 'sudo' in front of the iptables command to make it work.

The default setup will output something similar to this:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

As you can see, we are accepting anything from anyone on any port and allowing anything to happen.

When we're done, the output of that command should look something like this:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             127.0.0.0/8         reject-with icmp-port-unreachable 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https 
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:30000 
ACCEPT     icmp --  anywhere             anywhere            icmp echo-request 
LOG        all  --  anywhere             anywhere            limit: avg 5/min burst 5 LOG level debug prefix `iptables denied: ' 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere

There's too much there to go into much detail in this article, but the basics to pay attention to when you skim those firewall rules are 'ACCEPT', 'REJECT', 'INPUT', and 'OUTPUT'. Fortunately those are reasonably understandable in context. Rules can refer to incoming traffic ('INPUT') or outgoing traffic ('OUTPUT'), and they can describe whether to 'ACCEPT' or 'REJECT' the described connections. The rest of it determines the sort of traffic being controlled, like what port or packet type it's looking for.

Roll your own

Now to set up those iptables rules we want. If the output of 'iptables -L' wasn't an empty ruleset, or if you just want to be thorough, you'll want to flush the current rules from memory:

/sbin/iptables -F

We can now set up our own rules that allow local connections and keep established connections (which is how the root SSH connection on port 22 will still work when we apply the SSH port changes and apply the new iptables rules).

We'll also open port 80 and port 443 (the normal HTTP and HTTPS ports) and, of course, allow connections to our custom SSH port. Then we'll allow pings to the Slice and, effectively, reject all other attempts to connect to a port.

To make it easier to keep track of the rules you want iptables to use and to change them later, let's create a file to store them:

nano /etc/iptables.up.rules

Now check out our example iptables rules file. Copy and paste those rules into your new file, and edit the rules however you see fit. The comments should help you decide what to change. In particular, make sure you change the line opening port 30000 to whatever you chose as your custom ssh port.

The lines opening ports for a web server should provide a good template for opening ports for other services you may add to your slice later.

If you want more complex firewall rules (restricting outbound traffic as well as inbound, for example), you might do well to research iptables more after you're done with this basic setup.

Once you're happy with your iptables rules, save the file.

Implement your rules

To tell iptables to use your new rules, run the command:

/sbin/iptables-restore < /etc/iptables.up.rules

That will read in the custom rules from the file you just created. You can confirm that it worked by checking the rules again:

/sbin/iptables -L

See the difference between the first time we entered that command and now? Again, have a look at each line of the output and see where it marries up with the rules we entered earlier.

Although the rules are up and running, they are only active for the current session. If the Slice were to be rebooted they would be lost.

As such, let's ensure they are restored on a Slice reboot. We'll add a small script that the system will run when your network interfaces are started. Create the file by running:

nano /etc/network/if-pre-up.d/iptables

Add the following lines to the new file:

#!/bin/sh
/sbin/iptables-restore < /etc/iptables.up.rules

Save your changes, and then make the new script executable:

chmod +x /etc/network/if-pre-up.d/iptables

That should ensure that whenever your network interfaces are brought up (usually just at boot time), the firewall will be too.

Editing iptables later

You can repeat these steps if you decide you've made a mistake, or if you want to change any rules later. Just edit the rules file you created, flush the current rules from memory, then restore the edited rules.

The commands you'd use (without all the commentary) are:

nano /etc/iptables.up.rules
/sbin/iptables -F
/sbin/iptables-restore < /etc/iptables.up.rules

Good work surviving the iptables setup.

Note that if you decide to use a control panel type of program like virtualmin that can manage your firewall rules you'll want to either not use that part of the control panel, or remove what we've been using to manipulate iptables. A similar choice would have to be made if you look into using another method of managing firewall rules, like UFW or Shorewall. Having two processes controlling iptables rules can lead to some real conflict. If you find an alternative, just be sure that you choose it alone or that you go back to using /etc/iptables.up.rules exclusively.

Onward!

Reload sshd

Now we have our basic firewall humming along and we've set the ssh configuration. Time to test it. Reload ssh so it uses the new ports and configurations:

/etc/init.d/ssh reload

Don't logout as root yet...

Logging in with the new user

On your LOCAL computer, open a new terminal and log in using the administrative user (in this case, demo) to the port number you configured in the sshd_config file (for our example, 30000):

ssh -p 30000 demo@123.45.67.890

The reason we use a new terminal is that if you can't login you will still have the working root connection to try and fix any errors.

Slicehost also has an excellent ajax console so if it all goes horribly wrong, you can log into your slice from the Slicehost management area.

You should be greeted with a plain terminal prompt like this:

[demo@yourvpsname ~]$

Success!

We now know that the firewall and sshd_config work and we can log in.

Let's move on to part 2 which includes updating the install and installing some base programs.

  • -- PickledOnion (updated by Jered)

Article Comments:

Luke commented Tue Apr 29 10:33:27 UTC 2008:

You guys rock!

Steven K. commented Tue Apr 29 22:51:57 UTC 2008:

Did something change in this version of visudo? I'm having trouble editing. It seems as though the key mappings are all messed up. It was find on Gusty, but hardy is acting up.

Delete and backspace doesn't work right, and my arrow keys have been replaced with uppercase A and B etc.

I've never had this sort of trouble before.

Btw, I'm running leopard and using it's native terminal.

Any ideas?

PickledOnion commented Wed Apr 30 09:33:00 UTC 2008:

Hi Steven,

visudo uses 'vi' as the editor - you will need to google for a quick 'vim cheatsheet'.

I can't remember the keys offhand I'm afraid.

PickledOnion

Scott Miller commented Thu May 01 20:42:38 UTC 2008:

Or use nano /etc/sudoers

Darryl Hamilton commented Thu May 08 20:18:23 UTC 2008:

What you'll want to do is set vi (or in this case, vim) into nocompatible mode. To do this, type ':set nocompatible' (without the quotes) in any vi session.

To make that change permanent, create a file called .vimrc in your home dir, with 'set nocompatible' in it (without the quotes)

Eric commented Sun May 11 16:51:15 UTC 2008:

I had never used visudo before today, and it would have been helpful for me (and probably others that lack visudo or vi experience) to quickly explain that when the file opens they need to hit "j" until they get to the last line, then hit "o" to create a new line below the current line and puts them in insert mode to type the "demo ALL..." and the hit ESC and then type "ZZ" to save and exit.

chris commented Sun May 18 20:19:39 UTC 2008:

It's barfing on me at: iptables-save > /etc/iptables.up.rules if i try it (with sudo) while logged in as my admin user, i get permission denied. when i try it as root, i get: -bash: iptables-save: command not found

no idea

Jon commented Mon May 19 04:58:16 UTC 2008:

Chris, if you're not signed in as root, use:

sudo su -c "iptables-save > /etc/iptables.up.rules"

(include the quotes)

That got me too.

For the iptables -L part the second time, the first line reads:

ACCEPT all -- anywhere anywhere

Is this correct? Shouldn't it reject all from anywhere?

Ken commented Wed May 21 20:40:57 UTC 2008:

I'm curious how I would modify my firewall to allow access for sftp and also to allow access to mysql on port 3306 (or some other port). What entries would I need in the iptables.test.rules file? Also, can I just repeat the steps listed even if I have already followed the instructions above to create a firewall?

steve commented Wed Jun 04 13:16:02 UTC 2008:

On another post for setting up SSH keys on windows with putty

eric commented Thu Jun 05 18:55:30 UTC 2008:

If I remember right, it's generally a bad idea to edit /etc/sudoers except through visudo. It has extra checks to make sure you don't accidentally lock everyone out of sudo access.

Antonio commented Tue Jun 10 21:52:49 UTC 2008:

Thanks for these tutorials. They're amazing. You really narrow it down.

Ben Alman commented Wed Jul 02 11:52:26 UTC 2008:

If you're unfamiliar with vi, before launching visudo, type this into your shell:

export EDITOR=nano

Now, visudo should use nano instead of vi, which will make things a little easier for you.

Kenneth Bengtsson commented Wed Jul 02 16:49:07 UTC 2008:

Excellent article!!

Gavin commented Sat Jul 12 10:54:16 UTC 2008:

Perfect! Thanks!

Toord commented Tue Jul 15 19:01:30 UTC 2008:

Fantastic tutorial! Best I've read in a while. I'm well versed in setting up servers and I'm moving from Gentoo (for convenience reasons) and this article was very helpful.

eman commented Sun Jul 27 14:12:30 UTC 2008:

If you are having problems logging in via ssh with sshvulnkey public key denied. It is because your version of openssh has had a faw for the past 2 years (Debian based distros). You can test your keys on the server - ssh-vulnkey authorized_keys

Simply run apt-get install openssh-server on your local workstation and regenerate the keys and re-send your public key to the remote server. This will solve your problems.

Good luck. Hopefully this comment will be added to the main article.

Jacek commented Thu Jul 31 23:28:08 UTC 2008:

One question: how is sudo + "demo ALL=(ALL) ALL" different than running as root? Doesn't it give all the same privili^H^H^H^H^H^H^Hopportunities to mess up?

Trepex commented Wed Aug 06 13:46:35 UTC 2008:

In general, you just never want to do an interactive root login. Aside from advertising the fact that root logons are enabled, your root credentials could also be intercepted. Once your secure connection is established, everything is encrypted and you can safely su/sudo.

Trepex commented Wed Aug 06 13:48:16 UTC 2008:

... there's also the fact that you're making the attacker break two passwords to gain access, if you've been sly enough to use a different user password than your root password ;)

James commented Thu Aug 07 21:37:30 UTC 2008:

Regarding the iptables, and the suggestion that "if you are completing this step at a later date using the admin user, you will need to put a 'sudo' in front of the commands." Actually, we cannot use sudo to redirect output, so you need to do the following (note the quotes around the command): sudo bash -c 'iptables-save > /etc/iptables.up.rules'

Otherwise, these articles are all extremely helpful and set SliceHost apart from more generic hosting systems.

Richard commented Tue Aug 12 09:08:34 UTC 2008:

Ubuntu's Server Guide and Wiki suggest using ufw as the firewall. Ufw looks simpler than iptables.

Sidharth commented Tue Aug 19 15:32:54 UTC 2008:

I change the /etc/ssh/sshd_config file so that Port 30000 instead of Port 22 is used.

After /etc/init.d/ssh reload, I'm getting a connection refused at port 30000. ssh is still available at port 22.

What do you think I may be doing wrong?

Daniel commented Sat Aug 23 05:37:25 UTC 2008:

If you're using OSX, you should probably use vim rather than vi or nano (as the latter two have some kind of weird problem with keys).

PickledOnion commented Sat Aug 23 12:58:16 UTC 2008:

Daniel,

I use OSX all the time and have no issues with nano or vi (I personally prefer nano).

I wonder if you need to set the keyboard in your terminal application. I use iTerm and use the default settings with no issues.

PickledOnion

Dash commented Sun Aug 24 04:14:56 UTC 2008:

Thank you very much for this article - its a snap now to setup my slice!

Paul commented Tue Aug 26 04:57:12 UTC 2008:

in the iptables config, I'm doing as you say for my slice.

But how come replacing one line ..

-A INPUT -p tcp --dport 80 -j ACCEPT

.. with ..

-A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

.. seems to break the loading of the rules?

Yes yes, I'm some lame Java user needing Jetty or Tomcat on port 8080 !

Eric Fields commented Tue Aug 26 15:35:21 UTC 2008:

Perfect article. Up and running just fine. Some weirdness w/ the Macbook keyboard but quickly figured things out (hint: the fn key stands for 'magic')

Bob Sherron commented Tue Aug 26 15:42:44 UTC 2008:

@Darryl Hamilton: Thanks much for the set nocompatible tip. Works like a charm.

Jon commented Thu Aug 28 00:24:58 UTC 2008:

When I try to reload the SSH, I get:

ignoring bad proto spec: '30000'. /etc/ssh/sshd_config line 9: Bad protocal spec '30000'.

I switched the port to 30000 and copied the file exactly as you had it. Any ideas?

Jon commented Thu Aug 28 00:51:49 UTC 2008:

OOPS! Never mind. I got the protocol and port mixed up. I'm not supposed to run with scissors either.

Brent commented Sun Aug 31 03:32:23 UTC 2008:

+1 for Ken's question. How should I tweak these settings to enable MySQL access from another box (for replication).

blake borgeson commented Wed Sep 03 05:02:02 UTC 2008:

excellent guide. thanks.

eduardopa commented Wed Sep 03 20:21:26 UTC 2008:

When I apply th new rules, I get this erro: iptables-restore < /etc/iptables.test.rules
iptables-restore v1.3.8: Can't use -A with -A Any ideas? Thanks

PickledOnion commented Thu Sep 04 09:31:14 UTC 2008:

Eduardopa,

It would seem you have an error or typo in the test.rules file.

The rules work perfectly well (I use them most days with test Slices).

Double check the file for any errors.

PickledOnion

Quang Tran commented Thu Sep 04 15:51:38 UTC 2008:

eman: You rock! It took me over 6 hours to configure ssh working with public/private key in my slice using various methods without success until I tried your suggestion. Thanks a lot!

PickledOninon: can you add eman's suggestion to the article? It would definitely help.

djwonk commented Sun Sep 07 17:01:16 UTC 2008:

I suspect that you have put the pre-up line in the wrong place. I think it belongs with the primary interface, not the loopback one.

To repeat a comment that I put on the Feisty install page:

djwonk commented Fri Oct 12 18:39:59 UTC 2007 ago: In my case, the pre-up line should go after the 'iface eth0' line: auto eth0 iface eth0 inet static pre-up iptables-restore < /etc/iptables.up.rules

Putting it "just after 'iface lo inet loopback'" like you locked me out from external ssh access. I had to use the console to repair things.

James Foster commented Mon Sep 08 03:42:05 UTC 2008:

I have a screencast where I follow these instructions. You can view it at http://programminggems.wordpress.com/2008/09/07/slicehost/

GMAN commented Thu Sep 11 13:03:35 UTC 2008:

Hey this is a great tutorial, but have one minor problem. A geek friend is gonna help me out with developing and I want to give him ssh access. How is he supposed to login? Do I have to scp him a copy of the key? I know you said not to.

PickledOnion commented Thu Sep 11 15:55:40 UTC 2008:

Hi,

In your case gman, you will likely need to enable password authentication.

This does allow for brute force attacks on the SSH port but long, secure passwords will help.

PickledOnion

Spencer Alexander commented Fri Sep 12 20:53:54 UTC 2008:

I'm a bit of a linux noob, and I found this tutorial incredibly easy to follow! Thanks for the help Pickled!

An extra tip that might be helpful to users scanning the comments: add an entry to your local computer's .ssh/config file. The following would be a good option


host slice
 user demo
 hostname demoslice.com
 port 30000

This will not only keep you from having to type in -p 30000 every time you do something ssh related, but it will also allow you to set up other services (ie git repository) with ease!

Thanks again for the help Pickled.

Neil commented Mon Sep 22 00:36:49 UTC 2008:

I've gone through the instructions twice and it keeps coming back with "Operation Timed Out" when I try to SSH in with the user account. Any guesses?

James commented Wed Sep 24 05:54:14 UTC 2008:

Excellent tutorial. Thank you!

Carson commented Fri Oct 03 04:51:43 UTC 2008:

Spot on tutorial. Worked the first time for me. Thanks.

Dan Collis-Puro commented Fri Oct 10 03:53:10 UTC 2008:

@Gman - just have your buddy generate an SSH keypair and put his public key into your /root/.ssh/authorized_keys file. No need to enable password auth, and any SSH client worth using can auth with a public key.

A couple more comments - put a passphrase on your ssh keypair and use "ssh-agent" (via "ssh-add") and you won't need to type your passphrase for every connection (it's cached into ssh-agent). You get two-factor authentication for free.

I personally leave SSH on the default port and firewall it off from everywhere but a few IP addresses, but that's me. Better to lock down the port than move it around.

Juliano commented Mon Oct 20 05:05:44 UTC 2008:

Yes, this tutorial requires careful attention it seems - I chose not to change my sshd port, or anyhow hadn't restarted my ssh session - and then running the iptables config blocked the port I was using (same with a couple folks above, it seems), requiring a reboot of the server.

So, be sure to ensure that the port you are accessing the server through at the time remains open in the iptables config before testing it.

Juliano commented Tue Oct 21 02:15:55 UTC 2008:

Note, I was wrong in the above note - sorry! Established connections are not blocked, as explained later in the tutorial.

What I did, though, was

iptables-restore > etc.iptables.test.rules

note the wrong sign - now, this totally disabled connectivity until a reboot. I know what '<' and '>' mean in bash, too, so I should have known better!

Brenton commented Wed Oct 29 00:36:58 UTC 2008:

Just a note to those having problems with vim in Ubuntu hardy with it inserting wierd cahracters for the arrow keys, I figured out the problem.

Basically, hardy ships with the vim-tiny package instead of the vim package, and there's some difference that makes everything work OK in regular vim but not vim-tiny.

To fix, run sudo apt-get remove vim-tiny vim-runtime vim-common followed by sudo apt-get install vim-runtime vim-common vim

You might actually only have to remove vim-tiny and add vim but I wasn't sure so I did all the vim packages.

Fernando Correia commented Sun Nov 02 23:00:44 UTC 2008:

This command will show more info about the firewall rules:

sudo iptables -L -v

Rob commented Thu Nov 06 04:08:58 UTC 2008:

I can't setup sudo priviliges for one of the accounts I created with adduser. I visudo and added the line demo ALL=(ALL) ALL at the end of /etc/sudoers but I still get and error when I sudo from demo: sudo ls / [sudo] password for pts: Sorry, try again.

Nige commented Thu Nov 06 15:30:49 UTC 2008:

Really good series of articles.

Just some important things to keep in mind for setting up ssh that I found useful:

  1. Changes to /etc/ssh/sshd_config are not noted by the the ssh daemon until you load them with /etc/init.d/ssh reload. You must do this every time you edit the file to change the port, add a user, etc. Then the changes take place. If you don't do this reload then you are only doing password authentication and not key authentication. Worse still - you think you're fully secure because you may not know any better (like me for the last week).

  2. To add another user to ssh you can simply get him to generate the public-private key pair, then get him to email you public key and follow the instructions as above for his new user account.

  3. It's not a good idea to switch off passwords on the private key. You can still log on securely without the private key password with ssh_agent as follows:

  4. Go to /home/<your_acc>/.ssh directory on your local machine (not the slice)
  5. Type ssh-add <private>
  6. Enter private key password
  7. You can now log on more securely without pwd

  8. If you didn't add a pwd on your private key file at the start then you can still do this as follows

  9. Go to /home/<your_acc>/.ssh directory on local machine (not the slice)
  10. Type ssh-keygen -p
  11. You are prompted to enter relevant private key file name and to set new password on it.

angryrabbit commented Tue Nov 11 07:58:27 UTC 2008:

I've completed the tutorial (twice). When I attempt to SSH in, I'm still asked for a password. Given that I have PasswordAuthentication to "no", I cannot log in.

I'm on Leopard.

PickledOnion commented Tue Nov 11 11:14:37 UTC 2008:

Hi,

It is possible that when you setup the ssh keys on your local machine you set a passphrase.

Note that this is not the same as logging in with a password.

A passphrase is an extra security aspect in that you can enter a password for the key itself. It is not a password for the SSH login - hence it is called a passphrase.

If you don't want a passphrase to unlock your ssh key then you may need to create a new one and ensure you don't enter a passphrase when it is created.

If that is not the case, then I don't know what the issue may be as this setup has been used hundreds of times.

PickledOnion

angryrabbit commented Tue Nov 11 18:32:31 UTC 2008:

I ran through the tutorial again, this time forgoing a password for the SSH key, and I can now log in without a password. However, I had to type the following on my local machine (again, running OS X 10.5):

ssh-add nameof_mykey

After that it worked. I'll also add that I named my key something other than the id_rsa. While I can log in okay, I get the following error every time I do:

key_read: uudecode (bunch of characters) failed

Any ideas?

Budo Kam commented Wed Dec 03 09:53:50 UTC 2008:

Thanks for the well written tutorial! I can't wait to get my site up and running on a real host. I think I'm going to burn my copy of windows and learn unix after this...

David Jacobs commented Thu Dec 04 05:27:08 UTC 2008:

No matter what I do I can never save my sshd_config. I always get the following error: [ Error writing /etc/ssh/sshd_config: Permission denied ]

I have followed the article to the letter several time with the same result. If I log out and try again I get a warning about a .tmp file and no matter what I can proceed no further. Please help.

PickledOnion commented Thu Dec 04 10:59:47 UTC 2008:

David,

You are either not using sudo or have not set the user to be a sudo user correctly.

PickledOnion

Yashesh Bhatia commented Tue Dec 16 10:30:44 UTC 2008:

Really good article...

Matt commented Tue Dec 16 11:14:40 UTC 2008:

I need to use password authentication as I need access from several locations.

Are there any other settings in the supplied sshd_config file that need to be changed apart from 'PasswordAuthentication no' to allow me access. PuTTy is connecting but closing as soon as I enter my user password.

Nick W commented Thu Dec 18 01:09:33 UTC 2008:

Worked like a charm. Appreciate the time put into this.

Andy commented Wed Jan 07 07:55:07 UTC 2009:

I was getting crazy behavior when running the vi commands, so I just did a quick: apt-get install vim and everything 300% more sane.

Douglas commented Sun Jan 11 19:50:41 UTC 2009:

I've noticed that the /etc/network/interfaces file gets overwritten each time I get a new IP address assigned to the slice. Might be something worth paying attention to.

Matt commented Thu Jan 15 17:53:27 UTC 2009:

Hi - thanks for a great article. I have one annoying problem though - I have turned off root login, created the new user, allowed access to the user and set 'ALL' privileges. The new user can login just fine from SSH and SFTP - I can do most things I want but when I try to edit files using Coda (my SFTP client), I get a permission denied message. I have re-checked the "[myusernmae] ALL=(ALL) ALL" line and that seems to be intact. Any ideas?

Gurinder commented Fri Jan 16 08:06:18 UTC 2009:

Hi, Thanks for this great service. i just setup my slice and everything went fine. I was just installing proftpd on my slice.

i installed proftpd using "sudo aptitude install proftpd" command. proftpd is running as inetd. not as a standalone server.

But i am not able to connect to server using ftp client. I guess ftp ports 21 and 20 are not allowed in iptables firewall.

can you please help me on how to open ftp ports in iptables.

Thanks

Andy Hume commented Thu Jan 29 15:22:35 UTC 2009:

I've always locked the root account as well with passwd root -l

Is there still any value in that if root ssh has been disabled?

sipskin commented Thu Jan 29 21:31:17 UTC 2009:

How in the world does one get multiple SSH keys to work on a server? I can log in from my mac to my primary server no problem - the generated key works fine. I have then generated a public/private key from my second server and SCP'd the public key across to the primary server, and then edited the authorizedkeys file to add in the pub key, but it still asks me for a password. I have also tried creating a authorizedkey2 file on the primary server for the second pub key, but no luck. Any ideas?

dmsuperman commented Sat Jan 31 22:06:26 UTC 2009:

Just as a quick note, > redirects stdout into a file. If you don't have permission to edit that file, however, it'll fail. If you want to replicate this, pipe to sudo tee to write stdout to a file.

For example:

sudo iptables-save | sudo tee /etc/iptables.up.rules

JD Justice commented Thu Feb 05 02:44:48 UTC 2009:

@sipskin re: multiple SSH keys on a server... see here

hope that helps!

Ashutosh commented Sat Feb 07 02:00:55 UTC 2009:

What settings should I use in the IPtables to allow remote connections to MySql? Thanks!

ballona commented Mon Mar 09 11:30:18 UTC 2009:

I've made it wrong the first time, so I'd like to suggest a change:

Where you read: Let's assume you've decided that you want a firewall. Create the file /etc/iptables.test.rules and add some rules to it. nano /etc/iptables.test.rules Look at this example iptables configuration file.

I think you'd better add something like: Don't forget to change 3000 port in the rule bellow: -A INPUT -p tcp -m state --state NEW --dport 30000 -j ACCEPT

It's silly but I've made it wrong and could't log in again after restarting ssh until I fixed it.

Sorry for the english.

conficker commented Mon Mar 16 01:22:58 UTC 2009:

Thanks for this tutorial. I hate doing Linux stuff on my own, and I especially hate trying to figure out what things to do.

ahabman commented Mon Mar 16 17:39:52 UTC 2009:

Running the 'ssh-copy-id' command locally was a lot easier for me than the 6 manual commands shown here.

Kill Conficker commented Wed Apr 01 02:16:23 UTC 2009:

I didn't have any problems using nano with OSX

remove conficker commented Wed Apr 01 04:18:07 UTC 2009:

Wow! Thanks for this tutorial. I hate doing Linux stuff on my own, and I especially hate trying to figure out what things to do.

Fiona commented Tue Apr 14 16:01:03 UTC 2009:

Thanks a million for the above article. I am having one issue though...

I'm using Putty to ssh to my slice as my machine runs on windows. I followed the article except for

  1. the generation of the private public keys.. (I used this article for that bit... http://articles.slicehost.com/2009/2/4/ssh-puttygen) - as a result I left out SSH KeyGen
  2. I also left out the SSH Copy sections

I continued to follow this articles instructions from SSH Permissions where permissions get set.

Anyhow my issue is that logging on as Root works perfectly... however I get the 'Server refused our key' when attempting to logon as the new admin user set up at the very start. Anyone any ideas where i might be going wrong please?

Thanks

pbass98 commented Sat Apr 18 05:43:50 UTC 2009:

For those asking for how to allow mysql connection from another slice-- add a rule like this after the HTTP/HTTPS rules:

-A INPUT -p tcp --dport 3306 -j ACCEPT -i eth1

You can restrict further using the source's IP with the -s flag I think.

Jordan Lev commented Fri May 01 23:37:58 UTC 2009:

Note that you should set the ssh port number to something between 49152 and 65535. (see http://www.iana.org/assignments/port-numbers for details). I was having problems with the "iptables-restore" command, getting an "invalid port/service specified" error, because I inadvertently used a number higher than 65535.

Morten Blaabjerg commented Mon May 04 11:26:17 UTC 2009:

Remember to restart the SSH daemon :

sudo /etc/init.d/ssh restart

after you’ve finished changing your SSH settings and have save your changes to the sshd_config file.

Failing to do so got me locked out in my first attempt and I had to rebuild my slice.

aslan commented Thu May 07 19:16:49 UTC 2009:

thanks for the effort worked first time. thumbs up to slicehost so far :)

ManiSen commented Sat Jul 18 23:40:09 UTC 2009:

Excellent article - completed the whole set up in a few hours - good progress for a noob :) I am one happy camper here

the_guv commented Mon Aug 03 15:09:28 UTC 2009:

hey Picked Onion,

You're a ruddy legend, and referenced on my site for these cracking tuts.

Especial thanks for your Capistrano guides.

For what it's worth, I've put together a newbie-centric VPS setup guide, and that steps out this procedure for local Windows to remote Linux, using PuTTY ..

Set Up Unmanaged VPS (4 Newbies) - Part 5: Encrypt Data with OpenSSH & Auto-Login with PuTTY

Anyhow, hope that helps. Course, swapping to Linux will help even more ;)

scrum24 commented Mon Aug 10 09:08:39 UTC 2009:

The ajax console sounds really cool but it does not work on my Verizon storm phone. After I clicked on my slice, all the links on the right rails such as console, diagnosis, etc, are not going anywhere.

Abtin Forouzandeh commented Fri Aug 21 04:02:18 UTC 2009:

I followed these instructions precisely, however port 21 not blocked by the iptables configuration file. Any ideas?

ize commented Mon Sep 28 18:27:47 UTC 2009:

This is a very helpful tutorial, thank you so much!

One minor point of confusion for a relative n00b:

In the "SSH Permissions" section, the instructions give the example command

chown -R demo:demo /home/demo/.ssh

and then say to "change the 'demo' user and group to your admin user and group."

I started with a completely fresh install, and have not created any new groups. What should I do here -- just replace demo:demo with myAdminUser:myAdminUser ?

angeletti group commented Thu Oct 15 16:03:04 UTC 2009:

I loved this guide. I had a tough time at first because I'm on a Windows machine, but it was very helpful.

Spencer commented Fri Oct 16 08:54:18 UTC 2009:

Your articles are awesome -- much thanks. However, one question that I can't seem to get an answer to is how to combine the iptables with fail2ban. When I load the rules, it appears to wipe out my fail2ban rules. I can add the rules, restart fail2ban, then save them and use the new rules file to set my iptables, but this is somewhat painful, since it means I have to remember to do this whenever I add new fail2ban filters/rules. Any suggestions?

nick commented Tue Nov 03 08:17:14 UTC 2009:

It took me a long time to figure out that "authorized_keys" is the name of a file, not a directory. It's confusing because its plural, but there's only one key!

@ize When you create a new user Ubuntu creates a private group for that user with the same name automatically. So yes, you would do user:user in the chown command.

Luke G commented Mon Nov 09 14:41:36 UTC 2009:

I left a comment earlier about an error on "iptables-restore < /etc/iptables.test.rules". It said something about "no command given".

I haven't figured out exactly why it happened, but I noticed it did NOT happen if I did not do "sudo apt-get install emacs" before doing that command. I would do this regularly because I was too wimpy to use nano for editing.

Arthur commented Wed Dec 02 20:53:38 UTC 2009:

Good tutorial -- maybe I'm a dummy, certainly a newbie, but I think you should make it a little clearer that the point is to (1) disable SSH on the standard port (2) enable it on some random port (not 30000, right? Any scripter who knows about this tutorial will be looking for 30000, I assume.) and (3) enable public/private key encryption. I was a little confusy because I did half of this tutorial (didn't do the Putty part because I thought I could leave it for later -- it's not included inline) and then couldn't use SSH on port 22. Doh.

Part of my confusion was that the fact that the Putty tutorial was not even linked, let alone included inline, made me think it was somehow optional. Again, newbie problems, but this tutorial is for newcomers, right?

byron commented Sat Dec 19 21:47:11 UTC 2009:

Great tutorial.

I'm getting an error when trying to ssh: Permission denied (publickey).

I've checked everything a number of times including checking the public key appears to be the same in the authorized_keys. The only thing I can think of is that I deviated by using an existing idrsa/idrsa.pub instead of generating them.

After searching around I looked in the: var/log/auth.log on the server and found that some public keys were blacklisted. I have no idea if that's relevant, but it seems like a potential cause of the problem.

At any rate, going to try to generate new idrsa with a different name and append to the authorizedkeys to see if that works, but if anyone has run into this or knows this to be an issue, pls let me know.

Other potentially relevant info: running ubuntu in VMware on windows.

thanks in advance.

michael commented Thu Dec 24 23:13:44 UTC 2009:

You suggest editing visudo to give the person sudo privileges. The user management section of ubuntu's server set up (https://help.ubuntu.com/8.04/serverguide/C/user-management.html) suggests "$ sudo adduser demo admin" as an alternative and standard ubuntu way of doing things. sounds sensible to me. what do you think?

Jered commented Tue Jan 19 16:53:44 UTC 2010:

Sorry for the late responses, but...

Michael: Using "adduser demo admin" would not work with the slicehost image for Ubuntu 8.04. That command creates a user in the "admin" group, but the default sudo permissions do not grant sudo privileges to the admin group. You could make that work, however, by adding a line like "%admin ALL=(ALL) ALL" in visudo.

Byron: I suspect you may have rebuilt that slice, then tried sshing into the new build. Most ssh clients will reject a connection if the key stored in its knownhosts file doesn't match what the server reports back. You might see if there is an existing knownhosts entry for the IP address and remove it if you encounter that problem again.

Praveen Kumar Sinha commented Thu Jan 28 19:44:56 UTC 2010:

Awesome man!! Worked like this fantastic Thanks

Blerg commented Wed Apr 14 21:40:58 UTC 2010:

I'm getting the Permission denied (publickey) error. I did have to rebuild the slice but I also removed all the files in the .ssh dir on the server and client. Running on a mac. Is the info stored somewhere else? Same error when I tried to scp new key.

Blerg commented Wed Apr 14 22:26:00 UTC 2010:

Think I screwed something up so I'll rebuild and try it again. One thing that might be helpful for newbs like me is intermediary checks that we can do to verify our progress.

Blerg commented Wed Apr 14 22:44:32 UTC 2010:

Has something to do with the keys and rebuilding the server but I have no idea what as I've deleted the local keys multiple times at this point. Perhaps the mac or the ssh client caches the info somewhere. If anyone knows, I'd appreciate the help. Otherwise I'll just leave passwords on.

Jered commented Thu Apr 15 01:53:52 UTC 2010:

If you've rebuilt the slice, you should only need to remove the entry for the slice's IP address in your local public keys file (on a mac, that would be "~/.ssh/known_hosts" in the terminal). A rebuilt slice won't require ssh key authentication until you've enabled it (and you don't want to do that until you've uploaded a public key).

If you're using a graphical SSH client, try using the mac's included Terminal program to connect instead, since any ssh or scp commands run from the Terminal will definitely only use the known host keys in your ~/.ssh directory.

Lee commented Fri Apr 23 17:23:25 UTC 2010:

Worked first time!! And I didn't understand a word of it!!

Paul Trippett commented Fri May 28 18:38:23 UTC 2010:

Lee, Good documentation should just allow you to copy paste its contents :D

kz commented Sun May 30 20:45:50 UTC 2010:

Hi,

The example iptables configuration file seems to have been modified and seems to be broken. It worked earlier, now it does not. And it begins with "*filter". It seems to be truncated somehow.

http://articles.slicehost.com/assets/2007/9/4/iptables.txt

kz commented Sun May 30 23:46:12 UTC 2010:

Solved. Human error, as almost always... there is nothing wrong with the file.

zack commented Sat Jun 12 11:41:52 UTC 2010:

great tutorial - score: a perfect 10 ;)

Raydon commented Sat Sep 11 01:36:53 UTC 2010:

I'm a bit stuck at the part where I have to run /sbin/iptables-restore < /etc/iptables.up.rules. When I do this, it results in a "iptables-restore: line 34 failed". Anyone have any ideas?

So far this is an excellent tutorial. Thanks. :D

Jered commented Sat Sep 11 18:02:55 UTC 2010:

There's something about the 34th line of the iptables.up.rules file it doesn't like. That would fall a bit after the "Allow ping" section, I believe. Take a look at anything you may have added to that part of the file and check for typos. Essentially iptables tried reading each command from that file, one by one, and when it got to that line it found something it didn't understand.

Stefan commented Fri Sep 24 14:33:38 UTC 2010:

For those pulling their hair out trying to get authorized_keys to work with PuTTY and PuTTYgen--here's a easier solution:

After adding your user to the group wheel, open up PuTTYgen and create a key and save the public and private keys. Keep PuTTYgen open. Go back to PuTTY and "mkdir ~user/.ssh" then create authorizedkeys file with "nano ~user/.ssh/authorizedkeys". Go to PuTTYgen and copy the entire key from the box. Go back to PuTTY and paste the key into the window with a right click. Save the file with Control-O and you should get a response that one line was saved--only one line. The key is now on the server.

Continue with the steps in the article concerning changing permissions.

newly domain commented Thu Jan 06 07:08:23 UTC 2011:

Excellent tutorial. Worked on my ubuntu server. Thank you!

Josh commented Fri Feb 11 22:20:28 UTC 2011:

Hi there,

Just opened a Slicehost account and I'm trying to get set up to deploy Rails apps. I followed all the instructions, seemingly without issue, but in the end when I try to log in as the new administrative user, I get the error: ssh: connect to host XX.XX.XX.XXX port XXXX: Connection refused

When it came to setting up the sshd_config file, I just used the sample file and edited the particulars as instructed in the tutorial. I've already rebuilt my slice and tried everything again - no luck.

For the record, I started the Slice with Ubuntu 8.04.2 LTS (hardy). When choosing the set up, I noticed there was also a 32-bit option. Since the tutorial didn't specify, I went with the non-32-bit version.

Thanks in advance for your help!

Josh commented Fri Feb 11 23:03:48 UTC 2011:

Update to my last comment:

I've been experimenting with various options, and it seems that the problem is the SSH port. I can implement all the other instructions in the tutorial and it works fine and dandy - as long as I leave the SSH port set to 22. As soon as I change that, I can't log in. If I put it back (and reload SSH) I'm back in business. And yes, when changing the port I do it both in the sshd_config file and the iptables rules file.

So anyone have any idea why ssh seems to be stuck on port 22? Maybe I'm missing something but that certainly seems to be the source of the hang-up.

Thanks!

Z commented Fri Feb 25 00:32:46 UTC 2011:

Josh, maybe you're forgetting to put the port number when you ssh? You will need to "ssh -p NEWPORTNUMBER username@ip" since your local machine is still going to use port 22 by default

jturo commented Fri Apr 01 09:02:21 UTC 2011:

I get the exact same problem that Josh gets. Under Port 22 works fine but if i change it to a different port then it will refuse the connection.

jturo commented Fri Apr 01 10:06:18 UTC 2011:

I realized that my problem was that i was changing the wrong file. Instead of writing the sshdconfig file i was writing the sshconfig file. duhh!

Oubrwewar commented Thu Jan 24 17:38:50 UTC 2013:

Hi there! I could have sworn I've visited this website before but after looking at a few of the posts I realized it's new to me. Anyhow, I'm certainly pleased I found it and I'll be bookmarking it and checking back regularly!

django commented Mon May 20 15:44:04 UTC 2013:

I have a Django app, developing using Django means I don't have to be concerned so much with security at an application level, but I am concerned with things happening at a lower level than Django.

My question is, what does the "burst" 5/min stuff in the LOG section of the rules actually mean? Does it mean that abusers cannot fill my iptables log file (as a form of DOS) at a rate quicker than 5 log entries per minute, allowing an additional burst of 5 (presumably based on IP)?

all about computers commented Mon Jun 03 20:30:42 UTC 2013:

Today, I went to the beach with my children. I found a sea shell and gave it to my 4 year old daughter and said "You can hear the ocean if you put this to your ear." She put the shell to her ear and screamed. There was a hermit crab inside and it pinched her ear. She never wants to go back! LoL I know this is completely off topic but I had to tell someone!

LançamentosRJ commented Wed Jun 26 19:46:53 UTC 2013:

Excellent tutorial. Worked on my ubuntu server. Thank you!

search engine optimisation link bui.. commented Fri Jul 05 06:43:54 UTC 2013:

Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point. You definitely know what youre talking about, why waste your intelligence on just posting videos to your weblog when you could be giving us something informative to read?

My web-site: [search engine optimisation link bui..](http://un. ua/rus/article/431168.html "search engine optimisation link bui..")

Mais Imóvel Vendas commented Mon Aug 12 18:30:34 UTC 2013:

Excelent Tutorial, worked in my ubuntu server, you saved my life!

Mais Imóvel Vendas commented Mon Aug 12 18:32:44 UTC 2013:

Excelent Tutorial, worked in my ubuntu server, you saved my life!

Mais Imóvel Vendas commented Mon Aug 12 18:33:29 UTC 2013:

Excelent Tutorial, worked in my ubuntu server, you saved my life!

Mais Imóvel Vendas commented Mon Aug 12 18:33:59 UTC 2013:

Excelent Tutorial, worked in my ubuntu server, you saved my life!

Cidade Jardim Barra commented Mon Aug 12 19:18:51 UTC 2013:

Excellent tutorial, you saved my life! kk

Cidade Jardim Barra commented Mon Aug 12 19:19:14 UTC 2013:

Excellent tutorial, you saved my life! kk

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)