Em vez de adicionar cd ~/app && python serve.py em /etc/rc.local, tente colocar o caminho inteiro. Você está esperando que o processo init saiba que ~ é o seu diretório pessoal de alguma forma, mas o init inicia como root. Como o init é iniciado como root, ele procura em / pelo diretório do aplicativo e não pelo diretório inicial. Livre-se do ~ usando o caminho para o seu diretório pessoal.
Tente adicionar /home/whitecolor/app/serve.py a /etc/rc.local . ( pwd para encontrar o diretório do caminho.) Livre-se do python na frente do script serve.py, adicionando #!/usr/bin/python no topo do seu script. (digite um which python para encontrar o caminho, caso não esteja instalado no local normal)
Edit: Você disse "executar em segundo plano" e senti falta disso. Para executar um comando em segundo plano, adicione um & após o comando. Então, para o segundo plano do comando acima: /home/whitecolor/app/serve.py & Init geralmente não precisa do símbolo de fundo para iniciar um trabalho e executá-lo em segundo plano.
A excelente sugestão do DrDR não precisaria do mesmo & de tratamento após o comando na inicialização do cron, já que eles são executados em segundo plano por padrão.