It’s been a while since I’ve done anything to upgrade my PC. My last upgrade was “out-of-the-box”: a Ducky Shine 3 full-sized mechanical keyboard to replace my flimsy Rapoo wireless keyboard that kept me away from any serious games. This time, I’m addressing a more performance-related aspect of my PC.
What’s The Issue
I consider my PC good enough in all other areas: Intel Core i5-3570K, 2×4 gigs of Corsair Vengeance, a 2-gig MSI HD7850, a 250-gig WD Blue for the system and 3 terabytes of Hitachi for the primary storage.
Everything is great for now. Gaming is okay, with enough frames per second to prevent me from damaging my Ducky. But I’m not fond of the idea of shutting it down after a day’s work (well, a day’s play).
It takes about 21 seconds for my PC to display the Windows 8.1 login screen from a cold boot. This, I don’t mind. What I do mind is the time it takes from login to ready. Get this: 4 minutes plus. I could fall asleep in half of that! I have enough RAM and definitely enough juice in my i5 to crunch through the startup process easily. The bottleneck is clearly my WD Blue.
Choices, Choices
The course of action is clear on this one: ditch the HDD and get an SSD. It has to be (1) big enough so that I can migrate my existing HDD without problems, (2) fast enough so that grumpy is replaced with happy, and (3) doesn’t make me cry when I look at my bank account later on.
Five minutes of googling will tell you that in mid-2015, the one of the best all-around performer SSD is the Samsung 850 Pro. I quickly found a unit at a computer store near my home. At about $148 (or IDR 2 million) at the time of writing, it’s also not that expensive considering its performance.
Without really thinking much, I grabbed a unit and here it is:
Installation
I tried to follow the steps outlined here. On second thought, the new drive is actually larger than my old drive. I can skip the backup and the move-here-and-then-move-back-there routine, right? Awesome! Opening up my Corsair K550 to find a spot for the SSD is a walk in the park, and after fumbling with the box my P8Z77-V Pro came with to find an extra SATA cable the installation is straightforward.
Turning on the PC, I see that the BIOS detected the SSD and proceeded to log into Windows as usual. I skipped the backup, cloned my WD Blue to the 850 Pro, reconfigured the boot priority, and it’s good to go.
Benchmarks
The first thing I wanted to do after installing was test it out. I grabbed a copy of AS SSD Benchmark, and here are my initial test results:
Hmmm… Something’s not right. The benchmarks I found online suggested that the drive is capable of sequential write speeds of around 500 MB/s. So why is this unit lacking? I decided to check the cable and my hunch was right: I was using a 3 Gb/s SATA cable and was plugging it into an Asmedia SATA port. After swapping the cable out with a more suitable 6 Gb/s cable and plugging it into an Intel SATA port, the tests reveal numbers closer to the 500 MB/s mark:
Benchmarks are just benchmarks and I never believe that any benchmark could ever supersede real-life performance. So before installing the 850, I decided to measure the time it took for my PC to boot to login, and then from login to ready (which I set as the point in which my Rainlendar widgets show up). Here are the numbers:
Condition
BIOS Beep to Login
Login to Ready
Total
Initial (WD Blue)
25 seconds
About 4 minutes
4-5 minutes
Samsung 850 Pro w/ 3 GB/s cable
21 seconds
About 1 minute
90-ish seconds
Samsung 850 Pro w/ 6 GB/s cable
21 seconds
31 seconds
Under 60 seconds
These numbers (especially Samsung’s numbers) are not taken on the first successful boot. After I switched to the SSD and/or whenever I plug the SSD into a different SATA III port on my motherboard, the boot time will take forever. Well, no, actually it’s about 5 minutes. I’m assuming Windows 8.1 is doing it’s thing, but you should google it if you really want to know.
Conclusion
You can’t go wrong with an SSD upgrade. My total boot time is now improved from 4-5 minutes down to less than 60 seconds. That’s a roughly 5X increase. I bet Adobe Lightroom and everything else on my PC loads that many times faster also.
This is by far the easiest and most convenient way for me to squeeze that extra oomph out of my existing hardware. It may be a bit on the pricey side, especially for some people who contact me and say “hey, can you build me a PC for 250 bucks?” (you know who you are). I already spent about $2000 on my PC, so yeah, this is an enthusiast’s upgrade.
All said, I couldn’t be happier with the decision to join the SSD bandwagon. Also, I’m glad I’ll have an extra 250 gigs of storage to stash my music or whatever. This has been fun, and I’d recommend the 850 Pro for enthusiasts who want the extra bit of performance.
So we have our RaspberryPi ready, with MinibianPi installed and secured. If you’re like me, there’s already a ton of ideas about what kind of systems I want to set up in my house, and this is just from browsing and reading some awesome blog posts. What many people forget is that when you’re about to jump into the “smart home” or “personal cloud” bandwagon, there’s one thing that I believe you should have ready from day one: a secure reverse proxy.
Enter the RaspberryPi-Nginx-SSL combo.
Disclaimer
I am by no means an expert in server installation or maintenance. I do this for fun, and sometimes I get lazy and cut corners. Please don’t treat this as a you-must-do-this guide, but more of a this-is-what-I-did and I’d like to share it with you. If you spot any mistakes, please let me know and I’ll do my best to address it immediately.
What does a reverse proxy do, you say? Here‘s a good read. Now, why would a home user like me need to have a reverse proxy? Here are my reasons:
I want to have a single point of entry for all inbound traffic for my internal systems, using a single domain (or subdomain). All other systems (running on the same RaspberryPi or another unit downstairs) will be assigned a “virtual directory”.
I want to have all said inbound (and outbound traffic) encrypted using the strongest and latest cipher suites and have all reasonable optimization and security features enabled.
I want to have all internal traffic to be sent in cleartext to reduce the load of encryption protocols on my internal systems, and have a termination proxy do all the encryption work.
Your reasons may be different, and your mileage will surely vary. As with any tutorial you’ll find on this site, this is more of a “this-is-how-I-did-it” rather than “you-should-follow-my-example”. Proceed with your own considerations.
Why Nginx?
That question will probably spark a debate longer than this article. I’ve heard that Nginx is much more lightweight than Apache, and more suitable as a reverse proxy. But don’t take my word for it. Googling “nginx vs apache” will get you situated.
Prerequisite
This build is based on my previous article on how to set up a secure MinibianPi-based server. It’s up to you if you need as much security as I do.
Setting Up the Firewall
Previously, we’ve put a firewall in place that will only allow SSH connections. We’ll have to change it so that it allows HTTP and HTTPS (ports 80 and 443) from anywhere to connect.
Open the firewall rules file
sudo nano /etc/iptables.firewall.rules
Add the following lines anywhere in the file as long as it’s above the default deny statements (the “Drop all other inbound” line)
# Allow HTTP and HTTPS connections
-A INPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT
Matt Wilcox has written an excellent article about this on his blog, but I’ll re-write the steps here anyway.
Install Nginx and libssl-dev (just in case we need it later) using apt-get
sudo apt-get install nginx libssl-dev -y
Remove Nginx using apt-get
sudo apt-get remove nginx
Download the script and then open it for editing
cd
wget https://gist.githubusercontent.com/MattWilcox/402e2e8aa2e1c132ee24/raw/b88e2a85b31bcca57339c8ed8858f42557c3cf53/build_nginx.sh
nano build_nginx.sh
Perform the following edits:
First, go to the top of the file, you should see version numbers there saved as variables
#!/usr/bin/env bash
# names of latest versions of each package
export VERSION_PCRE=pcre-8.35
export VERSION_OPENSSL=openssl-1.0.1g
export VERSION_NGINX=nginx-1.7.1
We need to check the version numbers and make sure that they’re the ones we want to use. To check, go their respective websites, which we can find immediately below the code above:
# URLs to the source directories
export SOURCE_OPENSSL=https://www.openssl.org/source/
export SOURCE_PCRE=ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
export SOURCE_NGINX=http://nginx.org/download/
At the time of writing, I used the latest, which is PCRE v8.35, OpenSSL v1.0.2, and Nginx v1.7.10.
Remove the 64-bit flag. Raspbian Wheezy doesn’t qualify as a 64-bit operating system, nor does the RaspberryPi as a 64-bit computing device. So, we’ll find this line…
To be able to run the script, we need to make it executable. Let’s make it executable only for us and deny access to anyone else, because we’re paranoid like that.
sudo chmod 700 build_nginx.sh
Now all that’s left is run the script. This will take about 20 minutes, could be more. If you want to grab a beer, now’s the time.
sudo ./build_nginx.sh
After the build is done, check the output message and make sure that there are no errors. No errors? Great! Let’s open our browser and browse to the Pi’s address to check. If you see the Nginx welcome page, you’re all set. If not, recheck your build output, you might’ve missed something there.
That’s it! Now you have Nginx installed and ready to use. But of course the vanilla installation always has loopholes that we must fix. Onwards!
Optimizing Nginx Configuration
We could tune our Nginx installation to suit our needs. What I’m about to mention here are what I think would be beneficial for my setup. Your mileage will vary, so please take it with a grain of salt, do your research, and make an informed decision about your own setup.
All of the modifications in this section are done in the nginx.conf file, so let’s open it up:
sudo nano /etc/nginx/nginx.conf
First on my checklist is the number of worker processes. This is probably best set equal to the number of cores available on your processor, that way a worker process can be “attached” to a core. I use RaspberryPi 2 Model B, which has a quad-core processor, so I’ll be using 4 worker processes:
worker_processes 4;
Next, I want to optimize gzip compression, which will allow our server to save a bit of bandwidth when serving our content. Most of the settings are already there, I’m just adding a minimum length and some content types. Again, do your research and add content types or tweak settings as you see fit:
If you’re wondering, gzip_comp_level is how much compression we want. It accepts values from 1 to 9; 1 is the least compressed but fastest to compute and 9 is the most compressed but slowest to compute. With the limited power of our minuscule processor, I’m going with a middle ground value of 6.
Now, I want to have basic protection against DDoS attacks. I do this by limiting the timeouts for several events. Note that some of the settings below may already be present in the file, so do make sure that you’re not mentioning any duplicate settings (Nginx configtest will complain about it if you do, so don’t worry):
Last, to support longer domain names, I want to increase the hash bucket size. I find that 128 works best, but set it as you see fit:
server_names_hash_bucket_size 128;
That’s all there is to it. Let’s proceed with configuring our website.
Configuring the Website
This section assumes you already have dynamic DNS setup for your public IP address. If you haven’t got that setup yet, you can read my article on the topic and come back here to proceed.
It’s probably considered a good practice to not mess with the “default” settings; just copy it and work with a new file. That way if anything goes awry we can always revert to default. Here’s the complete set of commands that should get you set up, all in one go:
After executing that command we should have a copy of “default”, which is named “mysite”, and it is enabled. Now let’s open it up and edit it:
cd /etc/nginx/sites-available && sudo nano mysite
I don’t like too much comments in my config, so I just delete all lines that begin with “#”, then save and close. After that, let’s do a config test:
sudo service nginx configtest
If no errors show up, let’s reload Nginx to make the new settings take effect:
sudo service nginx reload
All done!
Securing Connections with Encryption
SSL Certificates
To encrypt communications between our server and the internet, we need to have an SSL certificate in place. I’m not going to go too deep into explaining what an SSL certificate is, because (1) I’m not that well-versed in cryptography and (2) this article is supposed to focus on the technicalities of implementing such encryption. If you’d like to know more, there are a lot of articles that you can read elsewhere.
Preparing a Private Key
To obtain an SSL certificate, we must first create a private key. This key must be known to no other than ourselves and must be kept secret in a safe place, preferably off-site and offline, to prevent unauthorized access. But that’s for the big players. For us, safekeeping in a USB flash drive that’s not plugged in unless needed will probably be sufficient.
Here are the set of commands we need to issue to generate our private key, which will reside in the /etc/nginx/ssl/ directory:
I recommend replacing ‘mysite’ with the domain name the certificate will be issued for to avoid further confusion.
The command starts the process of CSR and Private Key generation. The Private Key will be required for certificate installation. You will be prompted to fill in the information about your Company and domain name.
It is strongly recommended to fill all the required fields in. If a field is left blank, the CSR can be rejected during activation. For certificates with domain validation it is not mandatory to specify “Organization” and “Organization Unit” -you may fill the fields with ‘NA’ instead. In the Common Name field you need to enter the domain name the certificate should be issued for.
Please use only symbols of English alphanumeric alphabet, otherwise the CSR can be rejected by a Certificate Authority. If the certificate should be issued for a specific subdomain, you need to specify the subdomain in ‘Common Name’. For example ‘sub1.ssl-certificate-host.com’. I just used: mysite.com.
Once all the requested information is filled in, you should have *.csr and *.key files in the folder where the command has been run.
The *.csr file contains the CSR code that you need to submit during certificate activation. It can be opened with a text editor. Usually it looks like a block of code with a header: “—–BEGIN CERTIFICATE REQUEST—-” It is recommended to submit a CSR with the header and footer.
The *.key file is the Private Key, which will be used for decryption during SSL/TLS session establishment between a server and a client. It has the header: “—–BEGIN RSA PRIVATE KEY—–“. Please make sure that the private key is stored somewhere safe and secure as it will be impossible to install the certificate without it on the server afterwards.
Generating/Requesting a Signed Certificate
There are a few options where we can get a signed SSL certificate.
If you’re OK with a self-signed certificate (and the annoying warnings you get everywhere you connect to your home network), then this is the way to go. To sign your own certificate, issue the following command:
If you want to have a Certificate Authority sign your SSL certificate, you can apply for it at one of the Certificate Authorities. Just google “cheap ssl certificates” and you’ll get a list of candidates you might want to look at. I use one from GoGetSSL which at the time of writing costs $12.35 and is valid for 3 years. Just register at the provider of your choice and follow their instructions. However, keep in mind that you should never send your private key to anyone. Only submit your CSR.
Either way, we should end up with a *.crt file in our hands, and this is what we will use to secure our server using SSL/TLS. Before we can use the certificate, though, we must chain it together with the CA’s certificates. Here’s a pretty good article on COMODO’s site on how to do that.
Setting Up Nginx for SSL
After we have our certificate signed and ready, it’s time to configure Nginx to use those certificates. To make things easy to maintain, we’ll create another file that we will include in the main configuration file. The file will reside in the /etc/nginx/conf.d/ directory; Nginx is preconfigured to scan that location for additional configuration files.
If you would like to use different security settings or different certificates for your virtual hosts, you can put the additional configuration file outside of /etc/nginx/conf.d/ and include it manually in your http block in /etc/nginx/sites-available/mysite. Let’s create the configuration file:
sudo nano /etc/nginx/conf.d/security.conf
The list below will explain bit by bit what each setting will do.
Set Supported Protocols
We do this to support TLSv1 as the minimum standard because anything below that would compromise our security.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Set Server Cipher Preference
This will tell browsers to let our server decide what cipher suites to use throughout the session.
ssl_prefer_server_ciphers on;
Set Supported Cipher Suites
This defines what cipher suites we are supporting. I researched quite a bit for this list of cipher suites, and I finally settled using the modern compatibility cipher suite example from Mozilla. (actually that article is a pretty darn good resource, so please read it when you have the chance)
Enable Forward Secrecy
Forward Secrecy (or Perfect Forward Secrecy) is how servers and clients communicate using keys that are never sent through the wire using what’s called a Diffie-Hellman handshake. This ensures that should our private key be compromised, an attacker will not be able to decipher past communications. To perform Diffie-Hellman handshakes, both the client and server needs to send a prime number in cleartext. A Diffie-Hellman parameter file will determine the size of the prime number that is used. The bigger the safer, but generating a big file will take a lot longer. Mozilla recommends a minimum of 2048 bits, but I decide to use 4096 bits. It takes forever to generate on a Pi, so decide for yourself if you want that much bits. To use the parameter file, we include this in our security configuration file:
ssl_dhparam /etc/nginx/conf.d/dh4096.pem;
This setting only defines the dhparam file location. We need to generate the dhparam file by issuing the following command:
cd /etc/nginx/conf.d && sudo openssl dhparam -out dh4096.pem 4096
Enable HTTP Strict Transport Security (HSTS)
HTTP Strict Transport Security is a feature that will make browsers remember to always connect to our server using HTTPS. The first time a browser connects, it can use HTTP, but all subsequent connections will be “forced” to use HTTPS. The max-age here is set for 365 days (equivalent to 31536000 seconds). Mozilla recommends a minimum max-age of 6 months.
Enable OCSP Stapling
OCSP Stapling is a mechanism to “staple” certificate information from our own server so that we can skip contacting the Certificate Authority every time we need to authenticate an encrypted connection. This has the benefit of not sharing any request details to the Certificate Authority (thus increasing our privacy) and relieving the Certificate Authority of precious clock cycles that it would otherwise have to provide to authenticate every request to our server.
This tells Nginx to enable OCSP stapling and verification of OCSP responses, sets the location of our trusted certificates file, and configures Google’s public DNS as our resolver. Details of each setting can be found in the Nginx documentation. To use this feature, we must also prepare the comodo.trusted.pem file (COMODO is my CA, yours may be different). We do this by chaining all certificates like we did before except our entity certificate (the innermost certificate).
Enable Session Resumption
Session resumption is a feature that will allow a full SSL handshake to be abbreviated during subsequent requests. This shaves previous milliseconds off, which can decrease latency and improve efficiency. Here‘s a primer you can read to get acquainted with the concept. To enable session resumption both by cache and by session tickets, add the following lines:
Enable HTTP Private Key Pinning (HPKP)
I would like to start off by mentioning that at the time of writing this feature is not yet widely used, and I’m not even sure that it’s already a standard. Here’s the draft document if you’re interested in the hairy details. Suffice it to say for now that you should enable this feature only if you’re sure you know what you’re doing and what the consequences are. Please don’t blame me if your site’s visitors come complaining to you about authentication errors that only time can fix. You’re still on board? Well let’s go then! To generate your certificate’s SPKI pin, issue the following command:
Take note of the result. Now, before we actually commit to setting the HPKP header, I strongly urge you to generate a backup set of private key and CSR. This is considered a best practice to help you when your current private key is compromised and you need to revoke your certificate. If you don’t set this now and don’t have a backup, you’ll have your visitors stuck with invalid pins and they will have to wait out until the HPKP header has expired to be able to access your site with new certificates. Finally, to set the headers, insert the following in your security.conf file:
This should force all HPKP-compliant browsers to stop the SSL handshake if they detect that your public key has changed or been tampered with.
The security settings are now in place and ready to go, so let’s save and close the file. Next, we’ll configure the Nginx virtual host to use HTTPS exclusively.
Setting Up Nginx Virtual Host to Support SSL
This section is fairly easy to do. To do this, let’s open up the virtual host file that we’ve set up before:
sudo nano /etc/nginx/sites-available/mysite
We’ll introduce the following changes into the file:
Set Existing Server Block to Listen to Port 443 (HTTPS)
The existing server block we have in place listens to port 80 (HTTP). We need to change this so that it listens to port 443 (HTTPS) instead, and while we’re at it why not throw in SPDY support as well:
Add New Server Block to Listen to Port 80 (HTTP)
We can’t have a server that doesn’t listen to port 80 (HTTP), because most users will type in an address and the browser will assume that it’s HTTP. So, we create a new server block and place our redirection directives there:
Set Site Name and Certificates
In order for our site to work with HTTPS, we need to set the correct site name (FQDN) and certificates that go along with it. Let’s set it up in our HTTPS server block:
# Make site accessible from http://mysite.com
server_name mysite.com;
# certificate locations
ssl_certificate /etc/nginx/ssl/mysite.crt;
ssl_certificate_key /etc/nginx/ssl/mysite.key;
After we’ve made the changes above, let’s save the file and exit, and perform a configuration test:
sudo service nginx configtest
If that went well, we can go ahead and reload the configuration:
sudo service nginx reload
Now, we’re ready to test it.
Testing
Finally after all the security settings are in place (don’t forget to make copies of your private keys and store them somewhere safe!), it’s time to test. I like to use SSL Labs to test my settings, and I suggest you do too. Just head over to https://www.ssllabs.com/ssltest/index.html and enter your domain there. If you spot anything out of place, they have a lot of articles that can help you address it appropriately.
Here’s my test results:
If you’d like to see the details of the test, just go over to SSL Labs and run a test on this website.
What’s Next?
Now we have a secured Nginx reverse proxy that handles all incoming HTTP and HTTPS requests. We can tweak these settings as we see fit, and as more internal applications need outside access, but the scope of this article stops here.
As I write more articles based on this setup, I’ll update and post links in this section. So, stay tuned!
References and Further Reading
These articles have been instrumental in my writing this article and some of them may provide more insight for you if you’d like to dive deeper into the “why” instead of the “how”:
A RaspberryPi isn’t the most powerful computer around, nor is it equipped to perform server-grade mission-critical tasks. But a lot of people use it as their home-grown server, some have multiple units or clusters of them, and some companies even offer RaspberryPi data centers.
I’m a tinkerer. This means I make mistakes, I ruin one of my servers, and — more often than not — I re-install it from scratch because I don’t know how to fix it. Then I do it all over again. Setting up a base system that I can build on has become a somewhat mundane task. This post documents just that: my endeavor to create a secured minimum system from which I can build a RaspberryPi server.
Disclaimer
I am by no means an expert in server installation or maintenance. I do this for fun, and sometimes I get lazy and cut corners. Please don’t treat this as a you-must-do-this guide, but more of a this-is-what-I-did and I’d like to share it with you. If you spot any mistakes, please let me know and I’ll do my best to address it immediately.
Operating System Selection
The objective of this build is to prepare a minimum system that is reasonably secured and can be used as a base system from which we can build a RaspberryPi-based server. Note the keywords: minimum and server. We won’t need to have a desktop environment, let alone Minecraft. Let’s leave all unnecessary things out of the build.
To achieve the objective, I chose MinibianPi. It’s a stripped-down version of Raspbian which is quite up-to-date, and even supports Pi 2. I think it’s a great place to start.
Write the image to an SD card (there are instructions for Windows users, Mac users, and Linux users).
Login as root (password is raspberry), either directly or via SSH using Terminal if you’re on a Mac or PuTTY if you’re a Windows user. The image has SSH enabled by default.
Install raspi-config. We could just re-partition the SD card ourselves, but I would personally try to not mess with partitions.
apt-get install raspi-config -y
Run raspi-config, and then expand filesystem. We have to do this now to avoid running out of disk space when we start installing other stuff.
Reboot
Creating New User With Administrative Privileges
I believe this is one of the most important things to do, because the default ‘pi’ user on the Raspbian image is vulnerable enough if exposed to the internet, let alone having a system with a known root password.
First we need to update our repositories. I found out the hard way that if we do this any later, some installations just won’t work.
apt-get update
Next, we need to install sudo so that we can grant administrative privileges to non-root users.
apt-get install sudo
Alright, with that done, let’s add the new user.
adduser USERNAME
We have to set a password for this new user, but all other fields can be left blank.
To grant administrative privileges, we can add USERNAME to the sudo group.
adduser USERNAME sudo
With that done, we can reboot and login as USERNAME.
Securing The Operating System
Regenerating Unique Host Keys
The very first thing we need to do is regenerate the unique host keys.
Next we need to verify that the keys have indeed changed and make sure we’re still able to login. If you’ve been doing all this via SSH, try to login using another Terminal or PuTTY session. If you’re using PuTTY, you should see a warning and getting past it is simple. If you’re using Terminal or a Linux machine, you need to remove the host key from your known hosts file. Here’s how you do it if you previously logged in using the Pi’s IP address:
ssh-keygen -R 192.168.1.111
If that doesn’t work, and you’re okay with resetting your entire known hosts file, just delete it:
cd
rm .ssh/known_hosts
ssh ras.mydomain.com
Setting Up Key Pair Authentication for SSH
Next, we should prefer key pair authentication for SSH than the default password authentication. As long as we don’t lose our private key, that is. If you’re a Mac or Linux user, follow along. If you’re stuck with Windows, like I am, here‘s a good article about setting up key pair authentication using PuTTY.
On your own terminal (not on the Pi), do this to create your private and public key pair:
ssh-keygen
Follow the on-screen instructions to create the SSH keys on your computer. To use key pair authentication without a passphrase, press Enter when prompted for a passphrase. After completing this, 2 files will be created in the directory ~/.ssh (or /home/USERNAME/.ssh). The file id_rsa is your private key, and id_rsa.pub is your public key. Now, we need to upload the public key to the Pi. Let’s use SCP for this:
scp ~/.ssh/id_rsa.pub USERNAME@192.168.1.2:
Change 192.168.1.2 to your Pi’s reserved IP address.
Then, using the Pi’s console, on the Pi’s home directory, let’s create the .ssh directory:
mkdir .ssh
Next, move and rename the id_rsa.pub file to the .ssh directory and change permissions to secure it:
After that’s done, our Pi will be able to authenticate us using our public key. To try this out, logout from your Pi and try to login again. Instead of the usual SSH login prompt, you will be prompted to enter your passphrase if you have one. If you didn’t set a passphrase, you’ll be logged in immediately.
Disabling Password Authentication and Root Login
When we’re able to log in using key pair authentication, we should disable password authentication. While we’re at it, let’s disable root login as well:
Edit the file /etc/ssh/sshd_config
sudo nano /etc/ssh/sshd_config
Set ‘PasswordAuthentication’ value to ‘no’.
Set ‘PermitRootLogin’ value to ‘no’.
Restart SSH service.
sudo service ssh restart
Test by logging in without your private key, the attempt should be rejected.
Installing Iptables and Setting Up Basic Firewall Rules
To protect against attackers who take advantage of open ports, we should install iptables and set our default firewall rules. For now, we’ll just block everything except localhost, network pings, and SSH on port 22.
Install iptables using apt-get
sudo apt-get install iptables -y
Create a new file for our default firewall settings
sudo nano /etc/iptables.firewall.rules
Put the following text into the file, then save it and exit
*filter
# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT
# Accept all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow all outbound traffic - you can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT
# Allow SSH connections
# The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
# Allow ping
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "[NETFILTER] denied: " --log-level 7
# Drop all other inbound - default deny unless explicitly allowed policy
-A INPUT -j DROP
-A FORWARD -j DROP
COMMIT
Save, exit, nano, and make the file executable by root and not accessible by anyone else.
sudo chmod 700 /etc/network/if-pre-up.d/firewall
Test by rebooting and checking iptables right after you’re able to login again.
After confirming that the firewall is automatically restored on boot, let’s make the system logger divert all iptables-related rules to a different log file. This will come in handy when we need to analyze the logs, saving us the time to sort out the firewall log from other log entries. First, let’s create a new file:
After doing this you should have all log messages having the prefix [NETFILTER] stored in /var/log/netfilter.log.
NOTE: This build will eventually evolve into a server, which means we will need some more ports opened for our services to be able to function properly. When you have your services up and running locally but can’t access it from your network, just remember to check your iptables settings and make sure it’s not blocking your service port.
Installing fail2ban
The last item in our security checklist is installing a piece of software called fail2ban. It will monitor our log files for failed login attempts. After an IP address has exceeded the maximum number of authentication attempts, it will be blocked at the network level and the event will be logged in /var/log/fail2ban.log. To install it, issue the following command:
sudo apt-get install fail2ban -y
Getting The System Up-to-Date
Now the system is relatively secure and almost ready, but before we proceed with actually building the server, let’s upgrade everything first.
That’s it, now we have a secured minimum system ready to build. What servers can we build from this starting point? That depends on your imagination. Enjoy!
References and Further Reading
These articles are a good read if you’re into setting up your own RaspberryPi-based server. I believe they use the standard Raspbian Wheezy image for their tutorials, but most of the commands will run just fine.
Please have a look at them if you’re interested in learning more. Meanwhile, I’ll be documenting my own endeavor to build my server based on MinibianPi (as opposed to standard Raspbian Wheezy).
I’ve been messing around with my WordPress installation somewhat in the past few weeks, and I did that while I was gawking at the prospect of getting into the Game of Clouds. You see, the thought of having my own VPS for me to tinker with has refused to leave my mind these past few months.
Then the unthinkable happened: I deactivated my JetPack plugin, only to realize that I couldn’t reactivate it because the hosting company blocked access to xmlrpc.php. I began emailing the administrator, almost begging for him to open up access to my xmlrpc.php if only for a short while. But nothing happened. I guess he and the admins before his time put way too much security checks to really prevent xmlrpc.php to be accessed.
Eureka!
I thought this was my chance to migrate, because I never did have a good enough reason to do it in the past. The cheapest option I can find (shoutout to you good people at DigitalOcean.com) still costs more than four times my current service subscription, but I eventually decided that the benefits would outweigh the cost by n-fold. This is because moving into the cloud allows me to spawn (and kill) any server configurations as I like, and have root access (with reasonable security measures in place, of course) to do anything I could possibly want (even wipe out my entire filesystem if I was stupid enough).
So, this day marks the day I officially move to DigitalOcean’s cloud. The move was rather reckless, and I killed my own blog site for a few days in the process, but the experience was worth it.
To the clouds we go!
PS: I’ll be publishing the migration process within a few days. If that kind of stuff is right up your alley, please stay tuned 🙂
PPS: Even though I complain about xmlrpc.php being blocked on my previous subscription, I do know that it is for the good of everybody who paid to be on that shared hosting server. If you’re wondering how xmlrpc.php could use your site (and thousands like it, together) to bring down another server without you ever knowing anything about it, here‘s a good read.
My last two posts talked about how I used a Raspberry Pi to act as a low-power home server that now mainly serves two functions: as a NAS box and as a Torrentbox. Now, there are a multitude of other things that we can do with the Raspberry Pi, and a lot of them are controllable using a web-based interface. This gives us ease of control using a lot of devices, but still limits us to the confines of our local network. This post will attempt to address that.
Why I Did It
I don’t have a static IP assigned to my home internet connection. This means that each time something forces my modem to disconnect and then reconnect, I will have a different public IP address. Not good if I want to set up remote access for, let’s say, my Deluge web interface, because I’d have to first figure out what my public IP address changes to, which means I’d have to go home and… well, you get the idea.
Hence, Dynamic DNS, or DDNS.
Port Forwarding
The first thing I need to do to make this work is to enable port forwarding. If you don’t know what it is, a simple Google search will get you all the info you need. For the sake of example, I’ll be forwarding port 22 to my Raspberry Pi’s port 22 so that I can access its ssh from outside my network.
Next, I need to set up the Dynamic DNS service. What it does is basically enable me to route all requests to a particular URL so that it reaches the IP address of my choice. There are two ways to go about doing this.
Free Dynamic DNS Service
A popular free Dynamic DNS service, DynDNS, apparently has stopped its free service. One of the free alternatives that many people start to use is NoIP. After signing up for free, I get to choose my subdomain.
Why a subdomain? Because it’s free.
After I have my subdomain setup, I can go ahead and download the DUC Client for Linux. There are plenty of instructions on the internet on how to set this up on a Raspbian Wheezy. After I got it up and running on boot on my Pi, I can sit back, relax, and have my Pi update its public IP address to the NoIP service. I can then access my Pi’s secure shell from anywhere by instructing PuTTY to connect to [mysubdomain].[my-no-ip-domain] at port 22.
There’s a catch, though. I’d have to reactivate the free subdomain every 30 days. Well, they gotta do something to get me to buy their paid services, right?
But wait… there’s another way.
Free Dynamic DNS Service With My Own Domain
One of the perks of having my own domain and hosting at IdWebHost is that I can have as many subdomains as I’d like, and it’s dirt cheap. Check their pricing tables for more info, and I also have to say kudos to their customer support team that runs 24/7.
Before I do anything else, I setup a subdomain and confirm that it is indeed accessible. I also check my A records using the Zone DNS Editor. This could be different for each hosting company, so I won’t go into its details here; it’s best to ask their customer support directly.
The Dynamic DNS service of my choice is CloudFlare. I’ve heard a lot about them, and most are positive reviews. Most important, though, is that they offer a free service package. I then enter add my domain and let CloudFlare scan my DNS records.
After the usual sign-up – confirm email – activate 2-factor authentication routine, I proceeded with setting up my domain. I let CloudFlare scan my DNS records, and make sure that the new subdomain I added earlier is detected. If not, I just manually add a new A record, copying settings from my domain’s A record.
Next, I go and read an article about how to set up a custom script both on my hosted web and on my Pi to automatically check for public IP changes every 5 minutes. Just for fun, I changed the PHP script a bit so that it sends me an email every time it detects that my public IP address has changed.
Finally, I have to actually make the internet use CloudFlare’s DNS to make this all work. So I go to my IdWebHost management page, and set my nameservers to point to CloudFlare’s nameservers instead of IdWebHost’s. People usually say that DNS update propagation is slow as a slug and it takes up to 24 hours at a time to make the updates propagate. Not the case with CloudFlare. I just need to issue a “ipconfig /flushdns” on my Windows command prompt a few times to force an update.
A word of caution for this setup: because of the way some web hosting companies setup their CPanel sites as [domain]:[port], in other words it doesn’t use a subdomain for CPanel, you may need to tinker a little bit with your DNS settings so that CPanel doesn’t run through CloudFlare’s CDN. I chose to completely bypass CloudFlare’s CDN, except for this blog, because really the only thing I’m using from them is the Dynamic DNS service. Your mileage will vary.
Aftermath
Now, I have access to my home network that I can configure simply by configuring port forwarding on my router, and I don’t have to worry about my public IP address changing after a blackout (which unfortunately is a common thing on this side of the world).
As a matter of fact, my house just experienced a blackout today at about 9 a.m., at which time everybody was out working. At about 3.15 p.m., I was able to access my torrentbox from my cellphone. A query on my Pi’s uptime showed 12 minutes, which means that within 12 minutes of my Pi starting up, my new public IP was successfully propagated. Awesome!
This article is a follow-up of my earlier post about how to run a Raspberry Pi box as an always-on NAS box. I figured that since I only have a theoretical maximum of 4 concurrent clients in the house, and none of them are intensive users, I might as well squeeze out some more juice out of the Pi to run as an always-on torrentbox. Internet speeds in Indonesia are notoriously slow, and even downloading the Raspbian Wheezy image takes quite a while. Scheduling the download for off-peak hours (middle of the night, or mid-day when nobody is in the house) seems to be reasonable. I could even schedule the machine to be a seeder during those hours, and for once give back to the torrent community. (confession: I’m usually a leecher and stop seeding once my download is completed)
Choice of Clients
I like the idea of thin client access, which minimizes resource usage on the Pi itself. That’s why I chose Deluge. I did try using Transmission, and the fact that I need to run the Transmission desktop client on X so that I can access its web UI appalled me. So there you go, Deluge FTW!
Thin Client Installation
To install Deluge Thin Client, I did this as the pi user:
I log in as mysambauser to do everything, so that the thin client will run as mysambauser. Why? Because I think running it as a user who already has access to the USB HDD mounts makes a lot more sense than adding pi to the sambausers user group. If I wanted to be more careful, I’d create an entirely new user, let’s say deluge-user, put it in the sambausers group, and work from there. But I’m too lazy for that. Ha!
Alright, let’s login as mysambauser:
su mysambauser
Now let’s run deluged so that it generates a config file and then kill it afterwards:
deluged
pkill deluged
Alright, that should do it. Now, let’s create a backup of the config file:
Go the end of the file and add the user/password/access level of your liking. I went like this:
mysambauser:mysambauserpassword:10
Not the best, I know, but for the sake of example it’ll do. Now, go into the console:
deluged
deluge-console
Once inside, I went:
config -s allow_remote True
After that, I went like this to check that the setting is indeed changed:
config allow_remote
After I was sure remote is allowed, I exit the deluge console by, surely enough, typing exit. Then, I restart deluge daemon:
pkill deluged
deluged
Right. All done for the Pi for now. Time to install Deluge client on my PC. Downloads are available at the Deluge website. After installing it, I fire it up and go to preferences:
I then disable classic mode by unchecking that first checkbox:
I then have to restart Deluge client to load the classic interface, and be presented with the connection manager.
Next, I enter mysambauser’s credentials (leaving the port alone for now), and click connect.
Alright, so now I can control my Pi’s torrents from the comfort of my PC without having to keep my PC on to do the actual download. Cool bananas!
Web Interface Setup
Now, I’d like to have web access to my Deluge thin client. First, I log out of mysambauser’s shell to get back to pi’s shell by pressing Ctrl-D, then:
Then I run deluge-web and kill it, to make it create a configuration file that I can edit:
deluge-web -f
pkill deluge-web
The -f flag up there tells deluge-web to fork the current interface. If you don’t do it, the console will just sit there and wait and you’d have to exit by hitting Ctrl-C. Not pretty. Deluge should’ve given some warning about this. Anyway, I go and edit the configuration file:
sudo pico ~/.config/deluge/web.conf
I just change the port. I don’t like using the default port. Alright then, now I start deluge-web again:
deluge-web -f
Next, I browse from my PC to [Pi’s-IP-address-here]:[deluge-web’s-port]. I log in using the default password “deluge” and chose to change it immediately. Done.
Download Locations
I’d want my downloads to go to my external hard drive, lest my SD card become crowded and eventually run out of space. I do this by going to Preferences, Downloads, and set up my directories there. This is the reason why I use the mysambauser user instead of the default pi user, because pi doesn’t have access to my external hard drive.
I create four directories under /media/USBHDD1/Torrents: Backup, Completed, Incomplete, and Watch. Next, I add a samba share location to the Torrents directory. This way I can just drop torrents into the Watch folder or copy completed torrents from my Completed folder. Easy.
To test, simply copy a torrent file into the Watch directory. It’ll immediately disappear and be whisked to the Backup directory, and if you’re watching your desktop client or web UI, the torrents will show up and immediately start downloading. Delightful!
Setting Up Deluge to Start On Boot
To have the Pi start Deluge on boot, I’m going to skip the scripts and just use the download link the guys at HowToGeek.com provided:
After rebooting, if you can’t find the web UI, there’s something wrong either with the permissions, the hard drive mounting, or the init script itself. I won’t get into it as I experienced no problems at this point.
So, there you have it, I now have a Pi box capable of leeching (and seeding torrents) automatically just by dropping a torrent file into the Watch folder, and can be controlled either with a desktop client or web UI. As before, any comments or suggestions are welcome. Cheers!
I finally bought myself a Raspberry Pi Rev B from Element 14. I got it from an importer in Bandung, and I decided I’d go for a little shopping myself to the computer store to get me the tidbits. So here’s my kit.
Ralink RT5730 USB WiFi dongle with rotatable antenna (not shown)
The plan is to get it to work with my existing Western Digital MyBook 2TB external hard drive. I found so many tutorials on the interwebs about how to do this, but I guess I’ll just share my experience.
Hardware Assembly
The hardware assembly is pretty straightforward. The acrylic case snaps together without any problems, and voilà, my Pi’s got a casing.
Operating System
Next, I need to flash the SD card. It’s already got NOOBS on it, but I won’t be using it because I want to use the latest Raspbian Wheezy. I downloaded it from the Raspberry Pi website and flashed my SD card using Win32 Disk Imager. No problems here.
First Boot
OK, so here’s the first problem. I have two 22″ monitors connected to my PC, and nothing else. So I had to hijack the TV in the living room to do the first boot. Luckily I have a wireless mouse/keyboard combo handy, so less cables and it plugs into just one USB port on the Pi.
Default username is “pi” and password is “raspberry”. Upon first login, the Pi will automatically enter the raspi-config utility. Here’s my checklist on first boot (and second boot, for that matter):
Expand the filesystem. This needs a reboot. Do this to enter raspi-config:
sudo raspi-config
Enable SSH. To do this go to Advanced, SSH, then Enable SSH.
Exit raspi-config, and run the following command
ifconfig
Take note of the hardware address shown, because it’ll come in handy later on when I reserve an IP address for the Pi.
The Pi is now capable of running headless, so I shut it down.
sudo halt
Then I moved it to a better position, and connected it via UTP to my router. I also plugged in my external hard drive. I’ll be continuing on the setup remotely from the comfort of my PC. Before powering it up again, I decided to go ahead and reserve an IP address for the Pi, using the web-based router management UI. I won’t go into this because every router is different, but the point is to “map” the MAC address of the Pi’s network interface card to an IP address typically assigned by the router’s DHCP server. Alright, now power up!
System Update
The first thing I did after getting the Pi accessible by SSH (I use PuTTY for this) is to do a complete system update.
sudo apt-get update
sudo apt-get dist-upgrade
The upgrade process required that I download 460MB worth of debian packages. After the update completed, I decided to create a backup of the image, using Win32 DiskImager that I also use to write the system image on the SD card. This way, when I want to do a fresh install, I have the Pi updated to a more recent version and ready to run headless.
After saving the updated image, I decided to run raspi-config again to change my hostname. This is probably a good idea because if I buy another Raspberry Pi and run it using the image I just created, the two of them won’t have the same hostname.
Formatting The Hard Drive
I use a 2TB external hard drive connected via USB. I chose to format it using EXT3 for reasons I’ll explain later. I just went along with instructions I found using Google Almighty. First, I go into fdisk:
sudo fdisk /dev/sda
I deleted the one and only partition existing on the hard drive, and created a new primary partition that spans the entire disk. This is probably the scenario if you’re using a new hard drive. If you are going this route, just make sure you don’t have any data worth keeping on the disk. You have been warned.
Command (m for help): p
Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
58 heads, 60 sectors/track, 1122690 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002
Device Boot Start End Blocks Id System
/dev/sda1 2048 3906963455 1953480704 83 Linux
Command (m for help): d
Selected partition 1
Command (m for help): p
Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
58 heads, 60 sectors/track, 1122690 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002
Device Boot Start End Blocks Id System
Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-3906963455, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-3906963455, default 3906963455):
Using default value 3906963455
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
Explanation of commands in the order they are issued:
p: list partitions
d: delete partition
p: list partitions, to check that the partition is indeed marked for delete
n: new partition, and then just accept default values for a single primary partition
w: write the changes to disk
I then check that the partition is indeed available.
sudo fdisk -l
That command spits out the following result:
Disk /dev/mmcblk0: 15.7 GB, 15720251392 bytes
4 heads, 16 sectors/track, 479744 cylinders, total 30703616 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000b5098
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 8192 122879 57344 c W95 FAT32 (LBA)
/dev/mmcblk0p2 122880 30703615 15290368 83 Linux
Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
38 heads, 36 sectors/track, 2855967 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002
Device Boot Start End Blocks Id System
/dev/sda1 2048 3906963455 1953480704 83 Linux
Alright, now that I have the disk recognized as /dev/sda1, I need to make the filesystem.
sudo mkfs /dev/sda1
It takes a while to make the filesystem, so grabbing a cup of joe at this point might be a good idea.
Mounting and Sharing
After mkfs, the drive is ready to use but not yet mounted. So I prepared a directory for the share mount point:
sudo mkdir /media/USBHDD1
I decided to just add an entry into fstab and reboot the Pi so that I know for sure it works.
sudo pico /etc/fstab
In the editor, I added the following entry:
/dev/sda1 /media/USBHDD1 ext3 noatime 0 0
Next, I reboot the machine.
sudo reboot
After logging in, I tried running df to see if the hard drive is properly mounted.
Now that I’m sure I have the drive mounted properly on boot, it’s time to install samba. I found some instructions for how to do it, but it uses NTFS-formatted hard drives and is different than my setup. The samba part is, however, pretty much the same.
sudo apt-get install samba samba-common-bin
Next, it’s always a good idea to store a backup of any config file before editing it.
First order of business: activate user-based security. So I find the following line:
####### Authentication #######
# "security = user" is always a good idea. This will require a Unix account
# in this server for every user accessing the server. See
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
# in the samba-doc package for details.
# security = user
I uncommented the last line to activate user-based security by removing the hashtag:
# "security = user" is always a good idea. This will require a Unix account
# in this server for every user accessing the server. See
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
# in the samba-doc package for details.
security = user
To add shared folders, I add the following section to the very end of the configuration file:
[Public$]
comment = Public Shared Folder
path = /media/USBHDD1/Public
valid users = @sambausers
read only = no
[Apps$]
comment = Applications Repository
path = /media/USBHDD1/Apps
valid users = @sambausers
read only = yes
write list = mysambauser
[MediaCenter$]
comment = Media Center Repository
path = /media/USBHDD1/MediaCenter
valid users = @sambausers
read only = yes
write list = mysambauser
[private$]
comment = mysambauser's private folder
path = /media/USBHDD1/Users/mysambauser
valid users = mysambauser
read only = no
I repeated the private folder for every user I plan to have in the network to provide them with personal space. This would probably not be necessary if I had a huge SD card because I could just activate their home folders with read-and-write access. Unfortunately, that is not the case.
Now, I could just go ahead and create users who will have access to the samba shares, but I like to put them in a group together so I can easily assign privileges as a group. Thus the new user group sambausers:
sudo addgroup sambausers
Next, the users that will be in the group:
sudo adduser mysambauser -m -G sambausers
The -m flag creates a home directory for the user (in case we need it later), and the -G flag adds the new user to the sambausers group. I do this for every samba user I have. After that’s done, I set UNIX passwords and samba passwords for them (also repeat for all intended users):
sudo passwd mysambauser
sudo smbpasswd -a mysambauser
Now, I need to change ownership of the mount point, set its permissions, and create the correct directory structure inside it to match the samba configuration file.
I won’t go into the details of creating the directories, but I will point out that this will need to be done as the mysambauser user. All done! Now I can log out as mysambauser (and return to pi user) and start the samba service.
sudo /etc/init.d/samba start
Now I can browse to \\HOSTNAME from any Windows machine and map a network drive to the shares I just set up.
NOTE: If you use a firewall of some sort, please make sure your firewall allows access to ports 137, 138, 139, and 445 using TCP, and also port 137 using UDP. These ports are in use either by Samba itself or Windows hostname resolution (NetBIOS).
Performance and Conclusion
This article actually documents the second build. That’s why you may have noticed that the SD card in use is 16GB instead of 8GB. Also, I chose to use a wired connection to my router, I’m saving the Ralink for a second unit later on.
Performance is a lot better on this build. Here are the figures:
Test
Wireless Connection
Wired Connection
FAT32
EXT3
FAT32
EXT3
Copy 3GB file from desktop to Pi
400 ~ 600 kB/s
600 kB/s ~ 1 MB/s
600 kB/s ~ 1.5 MB/s
700 kB/s ~ 3 MB/s
Copy several files (2 ~ 10 MB each) from desktop to Pi
450 ~ 800 kB/s
700 kB/s ~ 1.2 MB/s
700 kB/s ~ 1.8 MB/s
700 kB/s ~ 4 MB/s
The figures are approximations only and should be taken with a grain of salt. I am by no means an experienced tester, and these are just some real-world results that I’ve got from my week-long use of the Pi unit. Further testing should include simultaneous read/write operations serving anywhere from 2-10 clients concurrently, but I’ll leave that to Anand or Linus or whoever else wants to do the testing.
Any comments or suggestions are welcome. Until next time. Cheers!
Animal Friends Jogja sedang mengadakan Open Adoption Program untuk seekor kucing bernama Kiko. Inilah dia Kiko!
*jreng jreng jreng*
Buat teman-teman yang tertarik untuk mengadopsi Kiko, bisa langsung menghubungi Animal Friends Jogja. Di website itu ada informasi lengkap tentang bagaimana caranya teman-teman bisa membantu Animal Friends Jogja dalam berbagai program, termasuk Open Adoption untuk kucing dan anjing. Teman-teman juga bisa memberikan dukungan dengan cara berbelanja aneka merchandise Animal Friends Jogja di AFJ Store.
Yuk, tunggu apa lagi, mari berkunjung ke AnimalFriendsJogja.org dan ikut berpartisipasi! Every little bit of help counts!
Lebaran tahun ini menjadi terasa berbeda karena baru kali ini aku harus menemani beberapa saudara yang datang dari jauh untuk berkeliling kota, dan bahkan hingga sampai ke Candi Borobudur. Begitu megahnya candi ini dengan ratusan stupa, patung Buddha, dan relief di dindingnya, apalagi mengingat candi ini dibangun pada masa kejayaan Dinasti Syailendra di abad ke-8. Begitu pentingnya Candi Borobudur sebagai peninggalan para leluhur kita, sampai-sampai UNESCO pun mengangkatnya sebagai World Heritage Site.
Bangga nggak sih kita punya peninggalan kebudayaan yang sedemikian hebat?
Oke, bangga itu biasa, semua orang juga bisa bangga, padahal bukan kita yang bikin candi itu, nenek moyang kita lah yang entah bagaimana caranya memahat ribuan batu dan menyusunnya satu-persatu sehingga bisa kita bangga-banggakan sekarang sebagai salah satu tempat ibadah umat Buddha yang terbesar di dunia.
Pertanyaan berikutnya adalah: sadar nggak kalau Borobudur itu milik kita? Kalau milik kita dan kita bangga memilikinya, seharusnya kita rawat nggak?
Beberapa foto di bawah ini menceritakan bagaimana bangsa kita menghargai warisan nenek moyangnya, yang juga adalah tempat ibadah untuk saudara-saudara kita umat Buddha.
Coba kalau ada orang yang melanggar batas suci masjid di kampung, atau ada orang tua yang mengajari anaknya penekan ke atas altar di Gereja Kotabaru Yogyakarta, pasti akan ada orang yang protes. Sama saja di Candi Borobudur, ini tempat ibadah, bung! Sudah terlalu banyak pula berita tentang betapa ganasnya para fotografer ketika memotret upacara Waisak di Candi Borobudur. Kalau kita sedang Misa Malam Natal atau Sholat Ied, lalu ada fotografer yang seenaknya nyak-nyakan di depan kita jeprat-jepret dengan lampu kilat menyala-nyala, kira-kira ibadah kita khusyuk nggak?
Itu dari sisi fungsi Candi Borobudur sebagai tempat ibadah. Belum lagi statusnya sebagai candi yang dibangun pada abad ke-8. Saya pernah mendengar bahwa wisatawan mancanegara jika berkunjung ke Borobudur di low season (berarti minim wisatawan baik domestik maupun mancanegara), selalu menggunakan jasa guide. Kebanyakan dari mereka akan mendengarkan dengan penuh perhatian semua hal yang diceritakan guide, dan yang lebih penting kebanyakan dari mereka akan mematuhi peraturan yang diberikan oleh petugas ataupun guide. Konon, salah satunya adalah tidak boleh memegang relief karena minyak dan/atau keringat di telapak tangan kita memiliki efek korosif untuk batuan yang sudah berusia ratusan tahun. Apa yang saya lihat dari wisatawan domestik kita sangatlah berbeda. Memanjat dinding stupa adalah hal yang biasa, apalagi sekedar duduk-duduk di tepi stupa atau meraba relief, atau bahkan berusaha merogoh patung Buddha di dalam stupa. Sudah diperingatkan pun tidak akan ada efeknya.
Duh, jangankan di candinya, baru masuk ke tempat parkir mobil pun sudah tidak ada aturan yang dituruti. Parkir serampangan dan seenaknya adalah hal biasa, apalagi ketika musim liburan di mana para tukang parkir yang jumlahnya sedikit itu sampai kewalahan dan bingung mau mengarahkan mobil yang mana lebih dulu.
Luar biasa bukan, bangsa kita yang kita banggakan ini, yang ternyata menghina dirinya sendiri. Bravo!
Rasanya cukup pas kalau artikel ini dipublikasikan di tanggal 17 Agustus 2014. Oke kita sudah merdeka, dan banyak yang mempertanyakan apakah kita sudah benar-benar merdeka. Pertanyaan lain yang mungkin bisa diajukan adalah: merdeka dari siapa?
Because our greatest adversary is indeed ourselves.
Jadi, yuk kita mulai dari diri sendiri mengubah sikap. Baca semua aturan dengan teliti, dengarkan semua perkataan petugas atau guide, dan patuhi semuanya dengan disiplin.
Bulan puasa di Indonesia selalu adalah bulan yang eventful. Tak terkecuali di Yogyakarta. Salah satu hal yang pasti muncul di saat bulan puasa adalah pasar takjil. Mendadak semua orang ingin berjualan takjil dan jalanan pun menjadi lebih ramai daripada biasanya di jam-jam menjelang saat berbuka puasa. Bagi orang yang suka berburu makanan dan cemilan tradisional khas daerah masing-masing, ini adalah waktu yang tepat!
Kali ini saya berkesempatan jalan-jalan ke Pasar Sore Ramadhan di Kauman. Yuk mari ikut melihat bagaimana suasananya.
Gang yang di hari biasa hanyalah salah satu dari sekian banyak “jalan tikus” di daerah ini disulap menjadi pasar jajanan dan makanan yang meriah. Seperti biasa, harganya sangat bersahabat dengan kantong kita, dan pilihannya banyak sekali. Berbahagialah hai para penyuka makanan dan cemilan!
Jika kita masuk lebih jauh ke gang ini, kita bisa melihat rumah-rumah penduduk yang seringkali masih asli jaman dulu. Mungkin nanti kapan-kapan akan ada photoblog post tentang rumah-rumah lawas di seputaran kampung Kauman ini.
Selamat menikmati perburuan takjil, dan buat saudara-saudaraku yang beribadah puasa, selamat beribadah, Gusti tansah mberkahi.