Upcoming events in GZ: GZRUBY and StartupGrind GZ
GZRUBY10 - Wednesday Jan 16 - 7:30PM
GZRUBY10 will be held at the Kudelabs offices this wednesday evening, starting at 7:30. GZRUBY is a gathering of ruby developers, Kudelabs is one of the sponsors along with other ruby development companies in the city. Its always a lot of fun and a great chance to meet up and talk web development. Find out more at the Guangzhou Ruby Group page.
StartupGrind Guangzhou with Clement Song - Friday Jan 25 - 6:30PM
StartupGrind is a global network of startup communities that was established to educate, inspire, and connect entrepreneurs in the city. Here in Guangzhou, we see it as a way to connect the English speaking world with the Chinese startup ecosystem. The second event features founder Clement Song, who founded eCitySky and successfully completed an acquisition to YY Inc. He's now with YY as the Directory of Platforms and Services, and was able to experience an IPO first hand. Find out more at StartupGrind Guangzhou Meetup page.
Hiring: Software QA Intern
Kude Labs (酷德实验室) is a growing software development firm focused on building high quality web applications. Our office is located in Guangzhou Wuyang District (广州市五羊邨).
We are happy to offer internship positions for students looking to improve their skills and gain some practical experience working on real-world projects. Intern positions are part time and can transition into a full time position after graduation. The majority of our full-time employees joined our team first as interns.
Software Testing Intern - Web applications
We are looking for smart Quality Assurance engineers for testing the Web Applications we develop.
Ideal candidates would have:
- Outstanding analytical thinking abilities
- Patient and precise work style
- Major in Computer Science or Mathematics related studies
- Experience with open source tools
- Excellent written and oral communications skills
- Self motivated and able to work independently
- Nonjudgemental, welcoming attitude
To Apply:
Please send an ENGLISH letter of interest, references and resume to: intern2012@kudelabs.com.
We look forward to working with you and welcoming you as a part of the Kudelabs family.
See more internship and full time positions at GZTechJobs.com
Join us for GZRUBY9: Wed Nov 21, 7:30PM
The 9th gzruby meetup will be coming to the kudelabs offices in Guangzhou next Wednesday, November 21st at 7PM. We'd love to see you there! You'll meet several members from the growing Ruby community in our city, and have a chance to present an idea you're working on or a gem you use. Feel free to invite anyone who may be interested in ruby, or learning more about Ruby on Rails.
Some small snacks and drinks provided. Many thanks to continued support from Strand Beer and this month's sponsor: Beansmile
See more about this event at gzruby.org: gzruby9 - Nov 21, 7:30PM
gzruby is the Guangzhou Ruby User's group, we meet once every 2 months to share tips and techniques, as well as show off recent projects.
Rails Two-factor Authentication
Given the problems passwords pose, isn't it time to offer people a second authentication factor? Your bank does it. Google does it. Even games do it. You can too. How hard is it to get Rails set up with a one-button six digit authenticator? Not hard at all! The hardest part was knowing where to look and what to get.
Close inspection of the dongles we already have revealed one name printed on them all: VASCO. VASCO provides the physical token you hold in your hand. We ordered a few of these. VASCO also provides the server software to authenticate tokens. The software comes in all sizes: enterprise, cloud, but for us the perfect match is just a C API called the VACMAN Controller. It runs on Windows, Linux, some more exotic OSes, but not Mac OS X.
How does it work? Each token has a serial number and contains a clock. When you press the button, the token shows a six digit one-time password based off that clock. Send the serial number, the password, and a little magic to the C API. It returns whether everything matches up right now. (So the clock on your server better be on time.)
How does the C API know whether the serial number and password match? In the beginning, VASCO creates a special encrypted file for you. It records how the clock and the serial number are synchronized. Before anyone can use their tokens, you have the API import the special file. It returns a data-structure with authentication information. Pass this magic struct with the serial number and password when authenticating. After authenticating, the data-structure is updated. Besides simple statistics like number of successful authentication attempts, the data structure stores information about token's internal clock. This allows the API to compensate for gradual time drift. The API itself is stateless. It's your job to keep track of the tokens and the data-structure.
Okay, but how does it work with Rails? As always, apply a little bit of glue. SWIG makes wrapping C APIs easy. This time was no exception though we did need to do a little more to allocate and free data-structures than usual. For the database, use ActiveRecord if that's your thing. We went with Sequal. We used two tables:
- One table maps user names to token ids.
- The other table maps token ids to magic data-structure blobs.
That's it really. We just use a script to import the import the token info. We don't use enough tokens to try to automate further.
It's sunny in Guangzhou
Summer in GZ brings some really hot weather! But it also brings tremendous rainstorms, clear skies after the rain, and excellent fruits. We currently have a blooming starfruit tree. I hope it is able to bear fruit later in the season.
Releasing Textilize gem for Rails3 without C extensions
Rails 3.X doesn't have the textilize and textilize_without_paragraph helper methods. Textilize is a gem brings back the missing method for Rails 3, and it includes the library RedCloth 3.0.4, which doesn't need to be compiled on server. Btw, The newest RedCloth is currently at 4.X though, it requires compiling C extension.
The reason we need this gem is that we use :textilize at a few places in our apps, and we don't need super fast RedCloth, we just need a working version that don't force us to install C extensions on various production servers. This could be useful for bundle-package usage, where you can rely on the bundle/cache gems.
Sourcecode: http://github.com/kudelabs/textilize
RubyGem: http://rubygems.org/gems/textilize
Deploying Rails apps on CentOS SELinux
In the course of our work we have come across a variety to linux flavors; RedHat Enterprise Linux, Ubuntu, and CentOS seem to be the most common. Lately I had to get a new CentOS box set up with a typical Rails stack, ruby, rvm, Passenger, mysql and so on.
There are plenty of articles that describe how to install the stack, and since the commands change constantly I won't bother with rehashing this. What I want to describe is how to make sure your Passenger app can be run on a locked down SELinux box safely.
The first thing to consider is what SELinux does. It is designed to combine all the best practices on server security and turn them ON by default. In fact, the only port that will respond to traffic is port 22, so that you can ssh in. Everything else is shut down.
Opening the Firewall
So the first thing we need to do is open things up a little bit more, specifically, we'll want to make sure outside people can access our web site, so lets open port 80 for http traffic. On CentOS, the system firewall is handled by the service iptables and configured in the file /etc/sysconfig/iptables. You can enable traffic on port 80 by adding this line to your iptables config file:
-A INPUT -m state –state NEW -m tcp -p tcp –dport 80 -j ACCEPT
However, you need to make sure to add this line before any REJECT lines, as the rules are read in order and any REJECT directives will override later ACCEPT directives. Once you have saved the file, you need to restart iptables
$ sudo service iptables restart
Directory Permissions
Another difference between Ubuntu and CentOS is that CentOS requires that your application directory, and all parent directories, have absolutely the right permissions. To accomplish this without chmod 777 -R * (please don't do that). I like to set up my groups and users carefully. First, off, I have a user that is in charge of logging in and managing the apps. Lets call her releng (release engineer). On the server, I use the /srv dir as it is at root, and has nothing inside. I add an apps dir, then set up my app inside of that, so I have a path like /srv/apps/appsauce (my new app is called appsauce). I then create a symlink ln -s /srv/apps /apps so that in all scripts and config files, I can simply use /apps/appname
Now, we want to make sure releng has access to all these files, so we run chown -R releng /srv. But the apache user needs access to these files as well! So I like to add apache to releng's group: usermod -G releng apache. Now that means we need to make sure the group releng has access to all these files. So we can run: chgrp -R releng /srv. At this point, we have a human user and a process user in the same group, accessing the same directory tree under /srv
Starting Passenger
If you are used to Ubuntu and simply install passenger right away without taking a breath, you probably will run into some trouble. If you check the httpd error logs (/var/log/httpd/error_log) you'll see that passenger is complaining about permissions. It seems that passenger is not allowed to do something it really needs to do. In this case, create files in the tmp directory.
In SELinux, not only are the ports shuttered, but the file permission structure is very strict. The apache user that is running passenger is not allowed to access files or directories it does not create itself, unless specifically given permission at the system level. Giving the apache user this access is a process I won't get into here. Luckily enough, there is a way to create permissions based on how an application is used. This article explains how to properly add permissions for passenger. The idea is to turn off SElinux, run the app, then turn the log of what the app asked for permissions-wise into a permissions policy for that app. Once the correct policy is in place, you can turn SELinux back on and run your app securely.
The article is missing an important piece of information though. If audit2allow has not been installed on your system, you won't find it in the yum repositories. You'll need to install the package policycoreutils-python
Finally
At this point, we should be able to run our app with SElinux turned on, and only port 22 and port 80 open for connections. This is a rock solid platform for your product or your clients applications. Leave a comment if you have any improvement suggestions.
Software Engineering Intern - 2012, Kude Labs
This position has been filled. Thanks to all the applicants!
Kude Labs (酷德实验室) is a growing software development firm focused on building high quality web applications. Our office is located in Guangzhou Wuyang New Town (广州市五羊新城).
We are happy to offer internship positions for students looking to improve their skills and gain some practical experience working on real-world projects. Intern positions are part time and can transition into a full time position after graduation. The majority of our full-time employees joined our team first as interns.
1. Software Development Intern- Web Applications, Ruby on Rails
We are looking for smart software engineers with experience and interest in Web applications. We develop in Ruby on Rails with a distributed team partly in China, partly in the US.
Ideal candidates would have:
- Outstanding analytical thinking and software design skills
- Computer Science background, or other Engineering degree and significant programming experience
- Experience with Ruby on Rails, or possibly other Web App framework and ability to learn quickly
- Experience using Linux or some other flavor of Unix
- Deep understanding of HTML and CSS
- Experience with modern Javascript and AJAX techniques
- Good written and oral communications skills
- Open-minded and willing to share ideas with others
- Self-motivated, cheerful, friendly, upbeat outlook
2. Software Testing Intern - Web applications
We are also looking for smart QA engineers for testing the Web Applications we develop.
Ideal candidates would have:
- Outstanding analytical thinking abilities
- Patient and precise work style
- Engineering background
- Experience with open source tools
- Some experience using Linux or some other flavor of Unix
- Excellent written and oral communications skills
- Self motivated and able to work independently
- Nonjudgemental, welcoming attitude
To Apply:
Please send an ENGLISH letter of interest, references and resume to: intern2012@kudelabs.com.
We look forward to working with you and welcoming you as a part of the Kudelabs family.
rails 3.2: cap deploy with assets
In rails 3.2, you need to precompile your assets (javascripts, stylesheets & images) when doing your deployment to server. There are couple ways to do this:
Add public/assets into your git branch before deployment.
You need to run the rake assets:precompile task locally, and then commit it into your staging or production branch. Note that you cannot commit into your development branch, otherwise, you have problem in development mode, e.g. javascript function got included twice.
The problem is obvious, you end up with extra files in your git repository, and your staging or production branch cannot be merged back into development branch.
Use Capistrano deploy/assets to precompile automatically on server.
This is quite easy to do. You just need to modify your Capfile:
# Uncomment if you are using Rails' asset pipeline
# load 'deploy/assets'
I use this method if the assets is quite tiny. However, it's not something super smart that will detect if your assets content really changes. It just simple precompile every time when you do cap deploy. So, it your assets is pretty large, your every deployment will be very slow. And if your server is quite cheap, you will notice that the server CPU is very high for a while.
I end up to write a cap task, cap deploy:assets, to do with it.
My idea is we don't deal with any assets precompile if just cap deploy, since it might be quite expensive. We wrote another deploy task deploy:assets for it, similar to the deploy:migrations.
- first, we precompile locally, to avoid high cpu on server, and I actually found that my MacBook Pro is much powerful than some of our servers.
- zip the whole public/assets directory as public/assets.tar.gz
- upload the public/assets.tar.gz to shared directory
- unzip the assets.tar.gz to shared/assets
- remove the public/assets & public/assets.tar.gz locally, so that we won't have problem in the development mode below is the task I wrote for this deployment behavior.
namespace :deploy do
task :ln_assets do
run <<-CMD
rm -rf #{latest_release}/public/assets &&
mkdir -p #{shared_path}/assets &&
ln -s #{shared_path}/assets #{latest_release}/public/assets
CMD
end
task :assets do
update_code
ln_assets
run_locally "rake assets:precompile"
run_locally "cd public; tar -zcvf assets.tar.gz assets"
top.upload "public/assets.tar.gz", "#{shared_path}", :via => :scp
run "cd #{shared_path}; tar -zxvf assets.tar.gz"
run_locally "rm public/assets.tar.gz"
run_locally "rm -rf public/assets"
create_symlink
restart
end
end
Updated: I saw a simple trick to speed up by checking if the assets directories changed or not before doing a assets:precompile task
namespace :deploy do
# http://stackoverflow.com/questions/9016002/speed-up-assetsprecompile-with-rails-3-1-3-2-capistrano-deployment
namespace :assets do
task :precompile, :roles => :web, :except => { :no_release => true } do
from = source.next_revision(current_revision) rescue nil
if from.nil? || capture("cd #{latest_release} && #{source.local.log(from)} vendor/assets/ app/assets/ | wc -l").to_i > 0
run %Q{cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:precompile}
else
logger.info "Skipping asset pre-compilation because there were no asset changes"
end
end
end
end
Teatime at Kudelabs

