Jenkins itself can be configured in many ways. The same applies for Jenkins jobs.
Probably the most easy way is to configure Jenkins manually and replicate its setup by backing up and restoring. Unfortunately, this means dealing with copying XML files.
But fortunately there are other ways.
When Jenkins starts, it checks
init.groovy.d directory and executes Groovy scripts there. To enforce locale I'm using a snippet.
// Copied from /var/lib/jenkins/init.groovy.d/set-locale.groovy
def pluginWrapper = jenkins.model.Jenkins.instance.getPluginManager().getPlugin('locale')
def plugin = pluginWrapper.getPlugin()
Another example of setting up Jenkins by Groovy scripts is located on https://gist.github.com/hayderimran7/50cb1244cc1e856873a4 - I'm using that snippet to setup local Jenkins users on test machines.
Jenkins Job builder
One approach of generating jobs is Jenkins Job Builder, which creates XML definitions jobs from YAML configurations. I don't like this approach personally as I consider it to be a bit hackish - looks like "generation of XML files without knowing what it means". But some big players are using this approach - JJB originates from Openstack.
Job DSL plugin
Another approach is Job DSL plugin (plugin page). There is special job type called seed job which creates other jobs from Groovy DSL. The seed job can pull the others job description in from Git, so you can easily version them, reuse them, etc.
I'm using personally this approach, as it was available when I started with Jenkins. I've even found some Jenkins tool to create DSL sources from existing jobs, but I'm not able to find it again.
To provide a seed job, you can still use the
The currently recommended approach is probably related to Jenkins Pipelines. You can store your building pipelines in the source VCS repository next to your code.
I haven't explored this very much, but I'm planning to do.