Algumas ideias que eu particularmente uso para fugir um pouco do "timezone hell":
* sempre use as mesmas funções de hora:
como o Everaldo falou, algumas funções retornam o horário UTC e outras baseado na timezone. Use uma ou outra em toda a sua app e evite misturá-las. Eu particularmente uso "0.ago" para tudo (ela retorna em UTC, com fuso +0). Ex.: 1.ago + 2.month.since - 1.day.ago
* não use as funções de data/hora do BD:
se você usa postgresql, evite usar o "now()" em uma consulta SQL, se uda o Mysql evite o "CURDATE()" e assim por diante. Pegue a data/hora via código Rails e passe para a query. Se necessário use tipos de dados sem timezone (no pg use o 'without timeone' ao criar um campo). Isto evita conflitos de fusos/horas desincronizadas entre web server e db server.
* somente nas views use funções com Timezone:
mantenha o BD sempre sem timezones, use somente UTC - como se fossem horas absolutas, não relativas ao local. Mas ao mostrar os dados, use helpers que considerem a timezone.
* se ainda assim tiver problemas force os seus arquivos de configuração a usarem os mesmos timezones:
verifique os arquivos de configuração do BD, o application.rb, force as conexões ao BD com comandos específicos do SGBD.
* NTP
o ntp é ótimo para manter a hora de todos os servidores sincronizados, mas ele não leva em consideração o timezone. Por exemplo, o horário de verão *não* afeta o seu retorno. O fuso deve sempre ser definido manualmente. O problema é que o fuso brasileiro por vezes não é definido segundo uma fórmula, mas sim conforme definição do ministério de minas e energia, que pode mudar a cada ano. Com isto as vezes pode ocorrer de o BD achar que para a data atual "Brasilia/Sao_Paolo" é +3 e o webserver achar que para a mesma data, mesmo estando na mesma máquina, a mesma definição de "Brasilia/Sao_Paolo" é +2.
Basicamente eu mantenho internamente tudo sem timezone (na verdade TZ +0), centralizo o controle da hora em um único responsável (a applicação Rails, ignorando as funções de data/hora de outros serviços), e somente ao externar a informação (na view) é que considero a TZ do usuário.