So recently I got into trouble running Redis on a host, because the data no-longer fits into RAM.
As an interim measure I fixed this by bumping the RAM allocated to the guest, but a real solution was needed. I figure there are three real alternatives:
Looking around I found a couple of Redis-alternatives, but I was curious to see how hard it would be to hack something useful myself, as a creative solution.
This evening I spotted Protocol::Redis, which is a perl module for decoding/encoding data to/from a Redis server.
It's a limited implementation which stores data in an SQLite database, and currently has support for:
It isn't hugely fast, but it is fast enough, and it should be possible to use alternative backends in the future.
I suspect I'll not add sets/hashes, but it could be done if somebody was keen.
As my previous post suggested I'd been running a service for a few years, using Redis as a key-value store.
Redis is lovely. If your dataset will fit in RAM. Otherwise it dies hard.
Inspired by Memcached, which is a simple key=value store, redis allows for more operations: using sets, using hashes, etc, etc.
As it transpires I mostly set keys to values, so it crossed my mind last night an alternative to rewriting the service to use a non-RAM-constrained service might be to juggle redis out and replace it with something else.
If it were possible to have a redis-compatible API which secretly stored the data in leveldb, sqlite, or even Berkley DB, then that would solve my problem of RAM-constraints, and also be useful.
Anyway the short version is that this might be a way forward, the real solution might be to use sqlite or postgres, but that would take a few days work. For the moment the service has been moved to a donated guest and has 2Gb of RAM instead of the paltry 512Mb it was running on previously.
Happily the server is installed/maintained by my slaughter tool so reinstalling took about ten minutes - the only hard part was migrating the Redis-contents, and that's trivial thanks to the integrated "slave of" support. (I should write that up regardless though.)
I’ve finally worked out how to create self-signed SSL certificates for multiple domain names with openssl.
These notes relate to Debian GNU/Linux, but the principles will apply to other operating systems.
The first step to make the process easier and repeatable in the future is to copy the default configuration file from /etc/ssl/openssl.cnf to a working directory where you can adapt it
Let’s assume that you’ve copied /etc/ssl/openssl.cnf to ~/project-openssl.cnf. Edit the new file and set the various default values to the ones that you need — that’s better than having to respond to openssl’s prompts every time you run it.
For real non-self-signed certificates, you would generate a certificate signing request (.csr) file, ready for a certificate authority to sign it for you. In that case, you need to follow the instructions at http://wiki.cacert.org/FAQ/subjectAltName.
But for a self-signed certificate, the subjectAltName has to go in a different place. Make sure you’ve got this line present and un-commented in the [req] section of the config file:[req] ... x509_extensions = v3_ca
and then this goes at the end of the [v3_ca] section:[v3_ca] ... subjectAltName = @alt_names [alt_names] DNS.1 = example.com DNS.2 = www.example.com DNS.3 = example.co.uk DNS.4 = www.example.co.uk
There is (apparently) a limit to the number (or total length) of the alternate names, but I didn’t reach it with 11 domain names.
It’s also possible to add IP addresses to the alt_names section like this:IP.1 = 192.168.1.1 IP.2 = 192.168.69.14
Then to create the key and self-signed certificate, run commands similar to these:openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout project.key -out project.crt -config ~/project-openssl.cnf cp project.crt /etc/ssl/localcerts/ mv project.key /etc/ssl/private/
Note that I move (rather than copy) the key to the private directory to avoid leaving a copy of it lying around unprotected.
You can check that the certificate contains all the domains that you added by running this:openssl x509 -in project.crt -text -noout | less Alternative approach
I haven’t tried this, but according to http://apetec.com/support/GenerateSAN-CSR.htm it’s also possible to create a CSR and then self-sign it like this:openssl x509 -req -days 3650 -in project.csr -signkey project.key -out project.crt v3_req -extfile project-openssl.cnf References:
Once upon a time I setup a centralized service for spam-testing blog/forum-comments in real time, that service is BlogSpam.net.
This was created because the Debian Administration site was getting hammered with bogus comments, as was my personal blog.
Today the unfortunate thing happened, the virtual machine this service was running on ran out of RAM and died - The redis-store that holds all the state has now exceeded the paltry 512Mb allocated to the guest, so OOM killed it.
So I'm at an impasse - I either recode it to use MySQL instead of Redis, or something similar to allow the backing store to exceed the RAM-size, or I shut the thing down.
There seems to be virtually no liklihood somebody would sponsor a host to run the service, because people just don't pay for this kind of service.
I've temporarily given the guest 1Gb of RAM, but that comes at a cost. I've had to shut down my "builder" host - which is used to build Debian packages via pbuilder.
Offering an API, for free, which has become increasingly popular and yet equally gets almost zero feedback or "thanks" is a bit of a double-edged sword. Because it has so many users it provides a better service - but equally costs more to run in terms of time, effort, and attention.
(And I just realized over the weekend that my Flattr account is full of money (~50 euro) that I can't withdraw - since I deleted my paypal account last year. Ooops.)
Happy news? I'm avoiding the issue of free service indefinitely with the git-based DNS product which was covering costs and now is .. doing better. (20% off your first months bill with coupon "20PERCENT".)
I have a Brother MFC-7360N printer at home and there is also one at work. I wanted to to get Cloudprint working with Android devices rather than use the Android app Brother provide, which is great when it works but deeply frustrating (for my wife) when it doesn't.
What I describe below is how to Cloudprint enable "Classic printers" using Debian Wheezy.Install CUPS
Install CUPS and the Cloudprint requirements.sudo apt-get install cups python-cups python-daemon python-pkg-resources Install the MFC-7360N Drivers
I used the URL below to access the .deb files required.
If you're running a 64-bit Debian, then install ia32-libs first.sudo apt-get install ia32-libs
Download and install the MFC-7360N drivers.wget -c http://download.brother.com/welcome/dlf006237/mfc7360nlpr-2.1.0-1.i386.deb wget -c http://download.brother.com/welcome/dlf006239/cupswrapperMFC7360N-2.0.4-2.i386.deb sudo dpkg -i --force-all mfc7360nlpr-2.1.0-1.i386.deb sudo dpkg -i --force-all cupswrapperMFC7360N-2.0.4-2.i386.deb Configure CUPS
Edit the CUPS configuration file commonly located in /etc/cups/cupsd.conf and make the section that looks like:# Only listen for connections from the local machine. Listen localhost:631 Listen /var/run/cups/cups.sock
look like this:# Listen on all interfaces Port 631 Listen /var/run/cups/cups.sock
Modify the Apache specific directives to allow connections from everywhere as well. Find the follow section in /etc/cups/cupsd.conf:<Location /> # Restrict access to the server... Order allow,deny </Location> # Restrict access to the admin pages... <Location /admin> Order allow,deny </Location> # Restrict access to the configuration files... <Location /admin/conf> AuthType Default Require user @SYSTEM Order allow,deny </Location>
Add Allow All after each Order allow,deny so it looks like this:<Location /> # Restrict access to the server... Order allow,deny Allow All </Location> # Restrict access to the admin pages... <Location /admin> Order allow,deny Allow All </Location> # Restrict access to the configuration files... <Location /admin/conf> AuthType Default Require user @SYSTEM Order allow,deny Allow All </Location> Add the MFC-7360N to CUPS.
If your MFC-7360N is connected to your server via USB then you should be all set. Login to the CUPS administration interface on http://yourserver:631 and modify the MFC7360N printer (if one was created when the drivers where installed) then make sure you can print a test page via CUPS before proceeding.Install Cloudprint and Cloudprint service wget -c http://davesteele.github.io/cloudprint-service/deb/cloudprint_0.11-5.1_all.deb wget -c http://davesteele.github.io/cloudprint-service/deb/cloudprint-service_0.11-5.1_all.deb sudo dpkg -i cloudprint_0.11-5.1_all.deb sudo dpkg -i cloudprint-service_0.11-5.1_all.deb Authenticate
Google accounts with 2 step verification enabled need to use an application-specific password.
Authenticate cloudprintd.sudo service cloudprintd login
You should see something like this.Accounts with 2 factor authentication require an application-specific password Google username: email@example.com Password: Added Printer MFC7360N
Start the Cloudprint daemon.sudo service cloudprintd start
If everything is working correctly you should see your printer the following page:
Add the Google Cloud Print app to Android devices and you'll be able to configure your printer preferences and print from Android..Chrome and Chromium
When printing from within Google Chrome and Chromium you can now select Cloudprint as the destination and choose your printer.References
The Tour de France visits YorkshireLocation: Yorkshire
1. This weekend I will apply to rejoin the Debian project, as a developer.
3. This is the end of my list.
4. I lied. This is the end of my list. Powers of two, baby.
I’ve previously blogged about how I sometimes setup a webcam to take pictures and turn them into videos. I thought I’d update that here with something new I’ve done, fully automated time lapse videos on Ubuntu. Here’s when I came up with:-
(apologies for the terrible music, I added that from a pre-defined set of options on YouTube)
(I quite like the cloud that pops into existence at ~27 seconds in)
Over the next few weeks there’s an Air Show where I live and the skies fill with all manner of strange aircraft. I’m usually working so I don’t always see them as they fly over, but usually hear them! I wanted a way to capture the skies above my house and make it easily available for me to view later.
So my requirements were basically this:-
I’ve already covered this really, but for this job I have tweaked the .webcamrc file to take a picture every second, only save images locally & not to upload them. Here’s the basics of my .webcamrc:-[ftp] dir = /home/alan/Pictures/webcam/current file = webcam.jpg tmp = uploading.jpeg debug = 1 local = 1 [grab] device = /dev/video0 text = popeycam %Y-%m-%d %H:%M:%S fg_red = 255 fg_green = 0 fg_blue = 0 width = 1280 height = 720 delay = 1 brightness = 50 rotate = 0 top = 0 left = 0 bottom = -1 right = -1 quality = 100 once = 0 archive = /home/alan/Pictures/webcam/archive/%Y/%m/%d/%H/snap%Y-%m-%d-%H-%M-%S.jpg
Key things to note, “delay = 1″ gives us an image every second. The archive directory is where the images will be stored, in sub-folders for easy management and later deletion. That’s it, put that in the home directory of the user taking pictures and then run webcam. Watch your disk space get eaten up.Making the video
This is pretty straightforward and can be done in various ways. I chose to do two-pass x264 encoding with mencoder. In this snippet we take the images from one hour – in this case midnight to 1AM on 2nd July 2014 – from /home/alan/Pictures/webcam/archive/2014/07/02/00 and make a video in /home/alan/Pictures/webcam/2014070200.avi and a final output in /home/alan/Videos/webcam/2014070200.avi which is the one I upload.mencoder "mf:///home/alan/Pictures/webcam/archive/2014/07/02/00/*.jpg" -mf fps=60 -o /home/alan/Pictures/webcam/2014070200.avi -ovc x264 -x264encopts direct=auto:pass=1:turbo:bitrate=9600:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf scale=-1:-10,harddup mencoder "mf:///home/alan/Pictures/webcam/archive/2014/07/02/00/*.jpg" -mf fps=60 -o /home/alan/Pictures/webcam/2014070200.avi -ovc x264 -x264encopts direct=auto:pass=2:bitrate=9600:frameref=5:bframes=1:me=umh:partitions=all:trellis=1:qp_step=4:qcomp=0.7:direct_pred=auto:keyint=300 -vf scale=-1:-10,harddup -o /home/alan/Videos/webcam/2014070200.avi Upload videos to YouTube
The project youtube-upload came in handy here. It’s pretty simple with a bunch of command line parameters – most of which should be pretty obvious – to upload to youtube from the command line. Here’s a snippet with some credentials redacted.python youtube_upload/youtube_upload.py --email=########## --password=########## --private --title="2014070200" --description="Time lapse of Farnborough sky at 00 on 02 07 2014" --category="Entertainment" --keywords="timelapse" /home/alan/Videos/webcam/2014070200.avi
I have set the videos all to be private for now, because I don’t want to spam any subscriber with a boring video of clouds every hour. If I find an interesting one I can make it public. I did consider making a second channel, but the youtube-upload script (or rather the YouTube API) doesn’t seem to support specifying a different channel from the default one. So I’d have to switch to a different channel by default work around this, and then make them all public by default, maybe.
In addition YouTube sends me a “Well done Alan” patronising email whenever a video is upload, so I know when it breaks, I stop getting those mails.
This is easy, I just rm the /home/alan/Pictures/webcam/archive/2014/07/02/00 directory once the upload is done. I don’t bother to check if the video uploaded okay first because if it fails to upload I still want to delete the pictures, or my disk will fill up. I already have the videos archived, so can upload those later if the script breaks.Automate it all
webcam is running constantly in a ‘screen’ window, that part is easy. I could detect when it dies and re-spawn it maybe. It has been known to crash now and then. I’ll get to that when that happens
I created a cron job which runs at 10 mins past the hour, and collects all the images from the previous hour.10 * * * * /home/alan/bin/encode_upload.sh
I learned the useful “1 hour ago” option to the GNU date command. This lets me pick up the images from the previous hour and deals with all the silly calculation to figure out what the previous hour was.
Here (on github) is the final script. Don’t laugh.Tweet